Функции с произвольным числом параметров *args и **kwargs
может принимать разное число аргументов и возвращает максимальное значение. Как можно самим определять такие функции? Делается это очень просто. Допустим, мы с вами хотим задать функцию для формирования маршрута к файлу:
F:\~stepik.org\Добрый, добрый Python (Питон)\39\p39. Функции.docx
И этот маршрут может состоять из нескольких частей. Причем, число фрагментов может быть произвольным. Опишем такую функцию. Я назову ее os_path(), а вместо списка параметров запишу звездочку и одну переменную args:
def os_path(*args): print(args)
Для начала, посмотрим, как это будет работать. Вызовем функцию с тремя строковыми аргументами:
os_path("F:\\~stepik.org", "Добрый, добрый Python (Питон)", "39\\p39. Функции.docx")
Не забываем здесь про экранирование обратных слешей. Выполним эту программу и в консоли видим, что переменная args ссылается на кортеж со значениями переданных трех аргументов. Здорово, да?! Чтобы функция принимала произвольное число аргументов, в ее объявлении достаточно у параметра прописать оператор *. Это оператор упаковки аргументов в кортеж и через переменную args мы сможем с ним работать.
Давайте теперь довершим нашу функцию и сформируем полный путь на основе его фрагментов. Сделать это можно с помощью знакомого нам метода join(), следующим образом:
def os_path(*args): path = "\\".join(args) return path
И, далее, вызвать эту функцию:
p = os_path("F:\\~stepik.org", "Добрый, добрый Python (Питон)", "39\\p39. Функции.docx") print(p)
Надеюсь, из этого примера, вам понятно, как объявлять функцию с произвольным числом фактических параметров. Хорошо, а что если мы передадим этой функции дополнительно один именованный аргумент:
p = os_path("F:\\~stepik.org", "Добрый, добрый Python (Питон)", "39\\p39. Функции.docx", sep='/' )
При запуске программы увидим ошибку, что функция не имеет такого формального параметра. Дело в том, что записывая объявление *args мы определяем лишь произвольное число фактических параметров, но не формальных. Как это можно поправить? Здесь есть, по крайней мере, два способа. В самом простом варианте, достаточно прописать этот формальный параметр в объявлении функции:
def os_path(*args, sep='\\'): path = sep.join(args) return path
И теперь никаких проблем с вызовом нет. Но, конечно, указать, какой-либо другой именованный аргумент мы не можем:
p = os_path("F:\\~stepik.org", "Добрый, добрый Python (Питон)", "39\\p39. Функции.docx", sep='/', trim=True )
Снова получим ту же самую ошибку. Так как же определить в функции произвольное число формальных параметров? Делается это с помощью следующего синтаксиса:
def os_path(*args, **kwargs): print(kwargs) path = kwargs['sep'].join(args) return path
Мы прописываем уже две звездочки, а затем, имя переменной, которая будет ссылаться на упакованные значения в виде словаря. Убедимся в этом, выполним программу и смотрите, в консоли коллекция kwargs действительно представляет собой словарь, ключами которого являются имена аргументов, а значениями – значения аргументов. Все очень удобно и просто, как всегда в Python!
Причем, коллекция **kwargs обязательно должна быть записана после коллекции *args, наоборот нельзя, так как вначале должны идти фактические параметры и только потом – формальные. Мало того, мы можем некоторые параметры указывать явно, например:
def os_path(*args, sep='\\', **kwargs): path = sep.join(args) return path
И, тем самым, гарантировать их существование внутри функции. А другие, передаваемые именованные аргументы, следует проверять, прежде чем использовать, например, для параметра trim сначала делаем проверку его существования в словаре kwargs, а затем, смотрим, чему равно это значение:
def os_path(*args, sep='\\', **kwargs): if 'trim' in kwargs and kwargs['trim']: args = [x.strip() for x in args] path = sep.join(args) return path
Если условие выполняется, то удаляем пробелы до и после фрагментов путей к файлу.
То же самое и с фактическими параметрами. Некоторые из них можно явно указать, при объявлении функции:
def os_path(disk, *args, sep='\\', **kwargs): args = (disk,) + args if 'trim' in kwargs and kwargs['trim']: args = [x.strip() for x in args] path = sep.join(args) return path
И тогда на первый аргумент будет ссылаться параметр disk, а остальные позиционные аргументы упаковываться в коллекцию args:
p = os_path("F:", "~stepik.org", "Добрый, добрый Python (Питон)", "39\\p39. Функции.docx", sep='/', trim=True )
Вот принцип, по которому объявляются функции с произвольным числом фактических и формальных параметров.
Вам осталось закрепить этот материал практическими заданиями и жду всех вас на следующем уроке.
Видео по теме
#1. Первое знакомство с Python Установка на компьютер
#2. Варианты исполнения команд. Переходим в PyCharm
#3. Переменные, оператор присваивания, функции type и id
#4. Числовые типы, арифметические операции
#5. Математические функции и работа с модулем math
#6. Функции print() и input(). Преобразование строк в числа int() и float()
#7. Логический тип bool. Операторы сравнения и операторы and, or, not
#8. Введение в строки. Базовые операции над строками
#9. Знакомство с индексами и срезами строк
#11. Спецсимволы, экранирование символов, row-строки
#12. Форматирование строк: метод format и F-строки
#13. Списки — операторы и функции работы с ними
#14. Срезы списков и сравнение списков
#15. Основные методы списков
#16. Вложенные списки, многомерные списки
#17. Условный оператор if. Конструкция if-else
#18. Вложенные условия и множественный выбор. Конструкция if-elif-else
#19. Тернарный условный оператор. Вложенное тернарное условие
#21. Операторы циклов break, continue и else
#22. Оператор цикла for. Функция range()
#23. Примеры работы оператора цикла for. Функция enumerate()
#24. Итератор и итерируемые объекты. Функции iter() и next()
#25. Вложенные циклы. Примеры задач с вложенными циклами
#26. Треугольник Паскаля как пример работы вложенных циклов
#27. Генераторы списков (List comprehensions)
#28. Вложенные генераторы списков
#29. Введение в словари (dict). Базовые операции над словарями
#30. Методы словаря, перебор элементов словаря в цикле
#31. Кортежи (tuple) и их методы
#32. Множества (set) и их методы
#33. Операции над множествами, сравнение множеств
#34. Генераторы множеств и генераторы словарей
#35. Функции: первое знакомство, определение def и их вызов
#36. Оператор return в функциях. Функциональное программирование
#37. Алгоритм Евклида для нахождения НОД
#38. Именованные аргументы. Фактические и формальные параметры
#39. Функции с произвольным числом параметров *args и **kwargs
#40. Операторы * и ** для упаковки и распаковки коллекций
#42. Анонимные (lambda) функции
#43. Области видимости переменных. Ключевые слова global и nonlocal
#45. Введение в декораторы функций
#46. Декораторы с параметрами. Сохранение свойств декорируемых функций
#47. Импорт стандартных модулей. Команды import и from
#48. Импорт собственных модулей
#49. Установка сторонних модулей (pip install). Пакетная установка
#50. Пакеты (package) в Python. Вложенные пакеты
#51. Функция open. Чтение данных из файла
#52. Исключение FileNotFoundError и менеджер контекста (with) для файлов
#53. Запись данных в файл в текстовом и бинарном режимах
#55. Функция-генератор. Оператор yield
#56. Функция map. Примеры ее использования
#57. Функция filter для отбора значений итерируемых объектов
#58. Функция zip. Примеры использования
#59. Сортировка с помощью метода sort и функции sorted
#60. Аргумент key для сортировки коллекций по ключу
#61. Функции isinstance и type для проверки типов данных
#62. Функции all и any. Примеры их использования
#63. Расширенное представление чисел. Системы счисления
#64. Битовые операции И, ИЛИ, НЕ, XOR. Сдвиговые операторы
#65. Модуль random стандартной библиотеки
#66. Аннотация базовыми типами
#67. Аннотации типов коллекций
#68. Аннотации типов на уровне классов
#69. Конструкция match/case. Первое знакомство
#70. Конструкция match/case с кортежами и списками
#71. Конструкция match/case со словарями и множествами
#72. Конструкция match/case. Примеры и особенности использования
© 2023 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Функция с переменным количеством аргументов в Python: *args и **kwargs
В этой статье мы расскажем, зачем нужны *args и **kwargs в Python и как их использовать.
В программировании, если нам нужно выполнять похожие действия, мы определяем функции для многоразового использования кода. Чтобы выполнить это действие, мы вызываем функцию с определённым значением — аргументом.
Предположим, у нас есть функция, которая складывает три числа:
def adder(x, y, z): print("sum:",x + y + z) adder(10, 12, 13)
После запуска будет выведено sum: 35 .
Во фрагменте кода выше у нас есть функция adder() с тремя аргументами: x , y и z . При передаче трёх значений этой функции на выходе мы получаем их сумму. Но что, если передать больше трёх аргументов в эту функцию?
def adder(x, y, z): print("sum: ",x + y + z) adder(5, 10, 15, 20, 25)
Из-за того, что здесь мы передаём 5 аргументов, при запуске программы выводится ошибка TypeError: adder() takes 3 positional arguments but 5 were given .
*args и **kwargs спешат на помощь
В Python можно передать переменное количество аргументов двумя способами:
Мы используем *args и **kwargs в качестве аргумента, когда заранее не известно, сколько значений мы хотим передать функции.
*args
Как было сказано, *args нужен, когда мы хотим передать неизвестное количество неименованных аргументов. Если поставить * перед именем, это имя будет принимать не один аргумент, а несколько. Аргументы передаются как кортеж и доступны внутри функции под тем же именем, что и имя параметра, только без * . Например:
def adder(*nums): sum = 0 for n in nums: sum += n print("Sum: ", sum) adder(3, 5) adder(4, 5, 6, 7) adder(1, 2, 3, 5, 6)
В результате выполнения программы мы получим следующий результат:
Здесь мы использовали *nums в качестве параметра, который позволяет передавать переменное количество аргументов в функцию adder() . Внутри функции мы проходимся в цикле по этим аргументам, чтобы найти их сумму, и выводим результат.
**kwargs
По аналогии с *args мы используем **kwargs для передачи переменного количества именованных аргументов. Схоже с *args , если поставить ** перед именем, это имя будет принимать любое количество именованных аргументов. Кортеж/словарь из нескольких переданных аргументов будет доступен под этим именем. Например:
def intro(**data): print("\nData type of argument: ",type(data)) for key, value in data.items(): print("<> is <>".format(key, value)) intro(Firstname="Sita", Lastname="Sharma", Age=22, Phone=1234567890) intro(Firstname="John", Lastname="Wood", Email="johnwood@nomail.com", Country="Wakanda", Age=25, Phone=9876543210)
При запуске программы мы увидим следующее:
Data type of argument: Firstname is Sita Lastname is Sharma Age is 22 Phone is 1234567890 Data type of argument: Firstname is John Lastname is Wood Email is johnwood@nomail.com Country is Wakanda Age is 25 Phone is 9876543210
В этом случае у нас есть функция intro() с параметром **data . В функцию мы передали два словаря разной длины. Затем внутри функции мы прошлись в цикле по словарям, чтобы вывести их содержимое.
-
- *args и **kwargs — специальный синтаксис, позволяющий передавать в функцию переменное количество аргументов. При этом, совсем не обязательно использовать имена аргументов args и kwargs ;
- *args используется для неименованных аргументов, с которыми можно работать как со списком;
- **kwargs используется для именованных аргументов, с которыми можно работать как со словарём;
- если вы хотите использовать и *args , и **kwargs , то это делается так: func(fargs, *args, **kwargs) , порядок следования аргументов важен;
Другие материалы по Python можно посмотреть у нас на сайте.