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:
Вопрос
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
)
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.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.
Решение
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:
Другие советы
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.
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.