Специальные параметры функции
По умолчанию аргументы могут быть переданы в Python функцию по позиции или явно по ключу. Для читаемости и производительности имеет смысл ограничить способ передачи аргументы - передать только по позиции, по позиции и по ключу или только по ключу.
Так выглядит объявление функции:
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| По позиции или по ключу |
| - Только по ключу
-- Только по позиции
Все, что идет до /
, можно передать только по позиции. Между /
и *
- по позиции и по ключу. Все, что после *
, - только по ключу.
Примеры
По позиции или по ключу
def standard_arg(arg):
print(arg)
standard_arg(2)
# 2
standard_arg(arg=2)
# 2
Только по позиции
def pos_only_arg(arg, /):
print(arg)
pos_only_arg(1)
# 1
pos_only_arg(arg=1)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'
Только по ключу
def kwd_only_arg(*, arg):
print(arg)
kwd_only_arg(3)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
kwd_only_arg(arg=3)
# 3
Комбинированные варианты
def combined_example(pos_only, /, standard, *, kwd_only):
print(pos_only, standard, kwd_only)
combined_example(1, 2, 3)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: combined_example() takes 2 positional arguments but 3 were given
combined_example(1, 2, kwd_only=3)
# 1 2 3
combined_example(1, standard=2, kwd_only=3)
# 1 2 3
combined_example(pos_only=1, standard=2, kwd_only=3)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'
Нюанс использования позиционных аргументов и **kwargs
def foo(name, **kwargs):
return 'name' in kwargs
Мы не сможем вызвать эту функцию так, чтобы она вернула True, потому что параметр name
будет привязан к первой позиции.
foo(1, **{'name': 2})
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: foo() got multiple values for argument 'name'
Однако использование /
позволяет это исправить:
def foo(name, /, **kwds):
return 'name' in kwds
foo(1, **{'name': 2})
# True
Когда что использовать
Только по позиции
- Нужно скрыть названия от пользователя
- Параметры не имеют значащих имен
- Если название параметра может измениться в будущем
Только по ключу
- Порядок не имеет значения
- Явная передача по ключу будет более читаема