Special use of args / kwargs

孤人 提交于 2019-12-22 09:29:20

问题


I need to do something like this:

def func1(a, *args, b="BBB", **kwargs):
    print "a=%s b=%s args=%s kwargs=%s" % (a, b, args, kwargs)

So that calling like this:

func1("AAAA", h="HHH", j="JJJ")

Produces the output:

a=AAAA b=BBB args=() kwargs={'h': 'HHH', 'j': 'JJJ'}

But it is not possible to put a default named argument after *args. (SyntaxError: invalid syntax)

  • Why is this not allowed?
  • Is there any readable way to implement this? The only way I know is b=kwargs.pop("b", "BBB"), but this is not very readable. I would prefer to have this in the function call definition, where it belongs: it is a parameter which will always have a value, either a default value or a user-given value.

EDIT

I could put b in front of args:

def func1(a, b="BBB", *args, **kwargs):
    print "a=%s b=%s args=%s kwargs=%s" % (a, b, args, kwargs)

But that would mean that this call:

func1("AAAA", "CCC", h="HHH", j="JJJ")

Assigns "CCC" to b, which I do not want. I want b to be a named arg, not a possitional arg.


回答1:


That's perfectly valid in Python 3 (demonstration); PEP 3102 introduced keyword-only arguments.

In Python 2.x you'll have to continue using kwargs.pop, or an appropriate decorator:

  • http://code.activestate.com/recipes/577940-emulate-keyword-only-arguments-in-python-2/
  • https://pypi.python.org/pypi/kwonly



回答2:


In Python 2,

The current Python function-calling paradigm allows arguments to be specified either by position or by keyword. An argument can be filled in either explicitly by name, or implicitly by position.

As a consequence def func1(a, *args, b="BBB", **kwargs) would be ambiguous and is therefore not allowed: in a call func1(1, 2), should args == () and b == 2, or args = (2,) and b == "BBB"?

This is why def func1(a, b="BBB", *args, **kwargs) is, on the other hand, accepted (even though it does not do what you want): b is always passed as the second argument, even in a call like func1(1, c=3, b=2) (it is equivalent to func1(1, 2, c=3)).

As ecatmur noted, Python 3 changed the way arguments are handled, which brings the flexibility you need.




回答3:


def func1(a, *args, **kwargs):
    b, k = (lambda b="BBBB", **k: b, k)(**kwargs)
    print "a=%s b=%s args=%s kwargs=%s" % (a, b, args, k)

could be an alternative.



来源:https://stackoverflow.com/questions/15545711/special-use-of-args-kwargs

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!