Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
666 views
in Technique[技术] by (71.8m points)

function call with named/unnamed and variable arguments in python

I have the following code:

def foo(func, *args, named_arg = None):
    return func(*args)

returning a SyntaxError:

  File "tester3.py", line 3
    def foo(func, *args, named_arg = None):
                                 ^

Why is that? And is it possible to define somewhat a function in that way, which takes one argument (func), then a list of variable arguments args before named arguments? If not, what are my possibilities?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The catch-all *args parameter must come after any explicit arguments:

def foo(func, named_arg=None, *args):

If you also add the catch-all **kw keywords parameter to a definition, then that has to come after the *args parameter:

def foo(func, named_arg=None, *args, **kw):

Mixing explicit keyword arguments and the catch-all *args argument does lead to unexpected behaviour; you cannot both use arbitrary positional arguments and explicitly name the keyword arguments you listed at the same time.

Any extra positionals beyond func are first used for named_arg which can also act as a positional argument:

>>> def foo(func, named_arg = None, *args):
...     print func, named_arg, args
... 
>>> foo(1, 2)
1 2 ()
>>> foo(1, named_arg=2)
1 2 ()
>>> foo(1, 3, named_arg=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for keyword argument 'named_arg'
>>> foo(1, 2, 3)
1 2 (3,)

This is because the any second positional argument to foo() will always be used for named_arg.

In Python 3, the *args parameter can be placed before the keyword arguments, but that has a new meaning. Normally, keyword parameters can be specified in the call signature as positional arguments (e.g. call your function as foo(somefunc, 'argument') would have 'argument' assigned to named_arg). By placing *args or a plain * in between the positional and the named arguments you exclude the named arguments from being used as positionals; calling foo(somefunc, 'argument') would raise an exception instead.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...