Python: передача параметров по имени вместе с kwargs
в Python мы можем сделать это:
def myFun1(one = '1', two = '2'):
...
затем мы можем вызвать функцию и передать аргументы по их именам:
myFun1(two = 'two', one = 'one')
кроме того, мы можем сделать это:
def myFun2(**kwargs):
print kwargs.get('one', 'nothing here')
myFun2(one='one')
поэтому мне было интересно, можно ли объединить оба метода, такие как:
def myFun3(name, lname, **other_info):
...
myFun3(lname='Someone', name='myName', city='cityName', otherInfo='blah')
В общем, какие комбинации мы можем сделать?
спасибо и извините за мой глупый вопрос.
2 ответов
общая идея такова:
def func(arg1, arg2, ..., kwarg1=default, kwarg2=default, ..., *args, **kwargs):
...
вы можете использовать столько из них, сколько хотите. The *
и **
будет "впитывать" любые оставшиеся значения, не учтенные иначе.
позиционные аргументы (предоставленные без значений по умолчанию) не могут быть заданы ключевым словом, а аргументы не по умолчанию не могут следовать аргументам по умолчанию.
Примечание Python 3 также добавляет возможность указывать аргументы только для ключевых слов, имея их после *
:
def func(arg1, arg2, *args, kwonlyarg=default):
...
вы также можете использовать (def func(a1, a2, *, kw=d):
), что означает, что никакие аргументы не захватываются, но что-либо после ключевого слова.
Итак, если вы находитесь в 3.x, вы можете создать поведение, которое вы хотите с:
def myFun3(*, name, lname, **other_info):
...
что позволит звонить с name
и lname
как ключевое слово-только.
Примечание это необычный интерфейс, который может раздражать пользователя - я бы использовал его только в очень специфическом использовании случаи.
в 2.x, вам нужно будет вручную сделать это, проанализировав **kwargs
.
вполне возможно, по крайней мере для Python 2.7. Аргументы ключевых слов присваиваются позиционным параметрам по имени, поэтому вы можете сделать
In [34]: def func(name, lname, **kwargs):
print 'name='+name, 'lname='+lname
print kwargs
....:
In [35]: func(lname='lname_val', name='name_val', city='cityName', otherInfo='blah')
name=name_val lname=lname_val
{'city': 'cityName', 'otherInfo': 'blah'}
официальные документы утверждают это таким образом: "Если аргументы ключевых слов присутствуют, они сначала преобразуются в позиционные аргументы следующим образом. Во-первых, для формальных параметров создается список незаполненных слотов. Если имеется N позиционных аргументов, они помещаются в первые N слотов. Затем для каждого аргумента ключевого слова идентификатор используется для определения соответствующий слот (если идентификатор совпадает с именем первого формального параметра, используется первый слот и т. д.). Если слот уже заполнен, возникает исключение TypeError. В противном случае значение аргумента помещается в слот, заполняя его (даже если выражение None, оно заполняет слот)." https://docs.python.org/2/reference/expressions.html#calls