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