Python,变长位置参数后面的默认关键字参数

我认为我可以在 Python 2中的函数调用中在变长位置参数之后使用命名参数,但是在导入 Python 类时会得到一个 SyntaxError。例如,我用下面的“ get”方法写作:

class Foo(object):
def __init__(self):
print "You have created a Foo."


def get(self, *args, raw=False, vars=None):
print len(args)
print raw
print vars

这个错误看起来像是:

def get(self, *args, raw=False, vars=None):
^
SyntaxError: invalid syntax

我希望能够以几种方式调用该方法:

f = Foo()
f.get(arg1, arg2)
f.get(arg1, raw=True)
f.get(arg1, arg2, raw=True, vars=something)

等等。

29752 次浏览

It does work, but only in Python 3. See PEP 3102. From glancing over the "what's new" documents, it seems that there is no 2.x backport, so you're out of luck. You'll have to accept any keyword arguments (**kwargs) and manually parse it. You can use d.get(k, default) to either get d[k] or default if that's not there. To remove an argument from kwargs, e.g. before calling a super class' method, use d.pop.


Note that in def get(self, *args, raw=False, vars=None):, the raw=False and vars=None have nothing to do with keyword arguments. Those are default argument values. Arguments with a default value may be passed positionally, and arguments without a default value may be passed by keyword:

def f(a=1): pass
f(2)  # works, passing a positionally
def f(a): pass
f(a=2)  # works, passing a by keyword

Similarly, keyword-only arguments are not required to have a default value. Coming after the *args argument is what marks them as keyword-only, not the presence of a default value:

def f(*args, a): pass
# a is a mandatory, keyword-only argument

Python's syntax doesn't allow variable args in function and keyword arguments with default value at the same time. If you must have keyword arguments along with arbitrary number of positional arguments, you need to allow arbitrary number of keyword arguments as well.

This is a common pattern to provide default values for keyword arguments, as well as allowing any number of positional arguments:

def foo(*args, **kwargs):
raw = kwargs.pop('raw', False)
vars = kwargs.pop('vars', None)

If you don't use the extra keyword arguments at all, you have nothing to worry about. This makes the function a bit less self-documenting, which you can make up with a properly written docstring.