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

88 投票
2 回答
30783 浏览
提问于 2025-04-16 17:17

我原以为在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)

等等。

2 个回答

51

在Python中,函数的写法不允许同时使用可变数量的参数和带默认值的关键字参数。如果你想在函数中使用位置参数(就是普通参数)和关键字参数(带名字的参数),那么你也需要允许使用任意数量的关键字参数。

这是一个常见的做法,可以为关键字参数提供默认值,同时也允许使用任意数量的位置参数:

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

如果你根本不使用那些额外的关键字参数,那就不用担心了。这可能会让函数的自我说明性稍微差一些,不过你可以通过写好文档字符串来弥补这一点。

76

这个功能是可以用的,但只在Python 3中有效。你可以查看PEP 3102。从“新特性”文档来看,似乎没有为2.x版本提供支持,所以你可能没办法使用这个功能。你需要接受所有的关键字参数(**kwargs),然后自己去解析它们。你可以用 d.get(k, default) 来获取 d[k] 的值,如果没有这个值,就返回 default。如果你想从 kwargs 中移除一个参数,比如在调用父类的方法之前,可以使用 d.pop


注意,在 def get(self, *args, raw=False, vars=None): 这个定义中,raw=Falsevars=None 和关键字参数没有关系。这些是默认参数值。带有默认值的参数可以按位置传递,而没有默认值的参数则需要用关键字传递:

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

同样,关键字专用参数不一定要有默认值。它们之所以被标记为关键字专用,是因为它们在 *args 参数之后,而不是因为它们有默认值:

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

撰写回答