Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Больше об именованных аргументах Python: Функции

Получение именованных аргументов в виде словаря

Позиционные аргументы можно получать в виде *args, причём произвольное их количество. Для именованных аргументов существует подобная возможность. Только именованные аргументы получаются в виде словаря, что позволяет сохранить имена аргументов в ключах:

>>> def g(**kwargs):
...     return kwargs
...
>>> g(x=1, y=2, z=None)
{'x': 1, 'y': 2, 'z': None}

По соглашению аргумент, получающий подобный словарь, принято называть kwargs от словосочетания "keyword arguments".

Аргумент *args в определении функции пишется после всех обычных позиционных аргументов перед первым аргументом со значением по умолчанию, а **kwargs пишется в самом конце, после последнего аргумента со значением по умолчанию. Давайте определим функцию, которая принимает все виды аргументов:

>>> def f(x, y, *args, kx=None, ky=42, **kwargs):
...     return (x, y, args, kx, ky, kwargs)
...
>>> f(1, 2, 3, 4, kx='a', ky='b', kz='c')
(1, 2, (3, 4), 'a', 'b', {'kz': 'c'})

Не нужно пугаться, в реальном коде редко какая функция использует все эти возможности одновременно! Но понимать, как каждая отдельная форма объявления аргументов работает и как такие формы можно сочетать — очень важно!

Передача именованных аргументов с помощью словаря

Как и в случае позиционных аргументов, именованные можно передавать в функцию "пачкой" в виде словаря. Для этого нужно перед словарём поставить… две звёздочки! Пример:

>>> def coords(x, y):
...     return (x, y)
...
>>> coords(x=1, **{'y': 2})
(1, 2)

Как вы видите, я и обычный именованный аргумент указал, и развернул в аргументы словарь — так тоже можно и это даже удобно! Попробуем функцию f из примера в начале урока вызвать с двумя наборами аргументов — одним для позиционных и вторым для именованных:

>>> positional = (2, 3)
>>> named = dict(ky='b', kz='c')
>>> f(1, *positional, 4, kx='a', **named)
(1, 2, (3, 4), 'a', 'b', {'kz': 'c'})

Обратите внимание на то, как я сконструировал словарь: я не написал литерал, а вместо этого вызвал функцию dict с несколькими именованными аргументами — так словарь ещё больше похож на "сохранённый набор аргументов"!

Также отметьте, что при подстановке аргументов "разворачивающиеся" наборы аргументов вроде *positional и **named можно указывать вперемешку с аргументами соответствующего типа: *positional с позиционными, а **named — с именованными. И конечно же, все именованные аргументы должны идти после всех позиционных!

Keyword-only аргументы

В Python 3 добавили возможность пометить именованные аргументы функции так, чтобы вызывать функцию можно было, только передав эти аргументы по именам. Такие аргументы называются keyword-only и их нельзя передать в функцию в виде позиционных. Выглядит функция с подобными аргументами так:

>>> def open_file(name, *, writable=False, binary=False):
...     
...
>>> f1 = open_file('foo.txt', writable=True)
>>> f2 = open_file('bar.bin', binary=True)
>>> f3 = open_file('raw.dat', True, True)

TypeError: open_file() takes 1 positional argument but 3 were given

Здесь * выступает разделителем: отделяет "обычные" аргументы (их можно указывать и по имени и позиционно) от "строго именованных". Такой разделитель можно использовать только один раз в одном определении. А ещё его нельзя применять в функциях с *args — да, не очень логично, но так уж вышло. Зато можно объявлять функции, у которых будут только строго именованные аргументы, для этого нужно поставить звёздочку в самом начале перечня аргументов.

Этот пример неплохо демонстрирует подход к описанию аргументов. Первый аргумент — имя файла, который будет открыт. Имя файла всегда присутствует, ведь нужно же что-то открыть, и связано по смыслу с именем функции. Поэтому этот аргумент можно не именовать. А вот writable и binary — необязательные аргументы. Которые получают ещё и ничего не говорящие значения True/False. Вполне логично ожидать, что вызов вида open_file('raw.dat', True, True) мало кому понравится! Поэтому опции и объявлены так, что могут быть указаны только явно.

Порядок аргументов при вызове функций

Отдельно стоит отметить, что при вызове функций вы имеете чуть больше свободы для задания порядка аргументов. Одиночные именованные аргументы могут идти вперемешку с подстановками наборов позиционных. Вот пример такого вызова:

>>> foo = [1, 2, 3]
>>> bar = "abc"
>>> # функция f здеcь та же, что и в первом разделе урока
>>> f(kx=42, *foo, ky=100, *bar)
(1, 2, (3, 'a', 'b', 'c'), 42, 100, {})

Ещё одна особенность заключается в том, что вы не можете для функции с сигнатурой вида f(x, *args) указать одновременно аргумент x по имени и при этом развернуть набор параметров. То есть вы не сможете сделать так: f(*foo, x=42).


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 120 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
Разработка веб-приложений на Django
29 сентября 8 месяцев

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»