Именованные аргументы могут передаваться как по позиции, так и по имени:
>>> def foo(a):
... print(a)
...
>>> foo(1)
1
>>> foo(a=2)
2
Если вы передадите позиционные и ключевые слова, они будут назначены в порядке.В вашем случае 1 присваивается первому позиционному аргументу (bar
), затем bar=2
присваивает аргумент с именем bar
.Таким образом, оба присваивают имя bar
, создавая конфликт.
Вы можете передать дополнительные аргументы после вашего имени:
>>> def foo(bar=None, *args):
... print('args=%r, bar=%r' % (args, bar))
...
... foo(2, 1) # bar=2, *args=(1,)
args=(1,), bar=2
ВPython3, вы также можете сделать только ключевое слово вашего параметра:
>>> def foo(*args, bar=None):
... print('args=%r, bar=%r' % (args, bar))
...
... foo(1, bar=2)
args=(1,), bar=2
Это также работает, если вы не принимаете никаких переменных аргументов:
>>> def foo(*, bar=None):
... print('args=%r, bar=%r' % ('undefined', bar))
...
... foo(bar=2)
args='undefined', bar=2
>>> foo(1, bar=2)
TypeError: foo() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
В Python2 разрешено только **kwargs
после *args
.Вы можете эмулировать именованные параметры, извлекая их из kwargs
:
>>> def foo(*args, **kwargs):
... bar = kwargs.pop("bar")
... print('args=%r, bar=%r' % (args, bar))
...
... foo(1, bar=2)
args=(1,), bar=2
Если вы хотите использовать только именованные параметры без переменные позиционные и именованные параметры, вы должны сами выдавать ошибки:
>>> def foo(*args, **kwargs):
... bar = kwargs.pop('bar')
... if args or kwargs:
... raise TypeError
... print('args=%r, bar=%r' % ('undefined', bar))
...
... foo(bar=2)
args='undefined', bar=2
>>> foo(1, bar=2)
TypeError