Python: Passing parameters by name along with kwar

2020-02-23 05:37发布

问题:

In python we can do this:

def myFun1(one = '1', two = '2'):
    ...

Then we can call the function and pass the arguments by their name:

myFun1(two = 'two', one = 'one')

Also, we can do this:

def myFun2(**kwargs):
    print kwargs.get('one', 'nothing here')

myFun2(one='one')

So I was wondering if it is possible to combine both methods like:

def myFun3(name, lname, **other_info):
    ...

myFun3(lname='Someone', name='myName', city='cityName', otherInfo='blah')

In general what combinations can we do?

Thanks and sorry for my silly question.

回答1:

The general idea is:

def func(arg1, arg2, ..., kwarg1=default, kwarg2=default, ..., *args, **kwargs):
    ...

You can use as many of those as you want. The * and ** will 'soak up' any remaining values not otherwise accounted for.

Positional arguments (provided without defaults) can't be given by keyword, and non-default arguments can't follow default arguments.

Note Python 3 also adds the ability to specify keyword-only arguments by having them after *:

def func(arg1, arg2, *args, kwonlyarg=default):
    ...

You can also use * alone (def func(a1, a2, *, kw=d):) which means that no arguments are captured, but anything after is keyword-only.

So, if you are in 3.x, you could produce the behaviour you want with:

def myFun3(*, name, lname, **other_info):
    ...

Which would allow calling with name and lname as keyword-only.

Note this is an unusual interface, which may be annoying to the user - I would only use it in very specific use cases.

In 2.x, you would need to manually make this by parsing **kwargs.



回答2:

It's possible at least for Python 2.7. Keyword arguments get assigned to positional parameters by name, so you can do

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'}

Official docs state it that way: "If keyword arguments are present, they are first converted to positional arguments, as follows. First, a list of unfilled slots is created for the formal parameters. If there are N positional arguments, they are placed in the first N slots. Next, for each keyword argument, the identifier is used to determine the corresponding slot (if the identifier is the same as the first formal parameter name, the first slot is used, and so on). If the slot is already filled, a TypeError exception is raised. Otherwise, the value of the argument is placed in the slot, filling it (even if the expression is None, it fills the slot)." https://docs.python.org/2/reference/expressions.html#calls