带*args和**kwargs的默认参数

74 python python-2.7

Python的2.x的(我用2.7),这是使用默认参数用正确的方式*args**kwargs
我在SO上找到了一个与此主题相关的问题,但这适用于Python 3:
使用*args,**kwargs和可选/默认参数调用Python函数

在那里,他们说这种方法有效:

def func(arg1, arg2, *args, opt_arg='def_val', **kwargs):
    #...
Run Code Online (Sandbox Code Playgroud)

在2.7中,它导致a SyntaxError.有没有推荐的方法来定义这样的功能?
我用这种方式工作,但我猜有更好的解决方案.

def func(arg1, arg2, *args, **kwargs):
    opt_arg ='def_val'
    if kwargs.__contains__('opt_arg'):
        opt_arg = kwargs['opt_arg']
    #...
Run Code Online (Sandbox Code Playgroud)

nne*_*neo 68

只需将默认参数放在*args:

def foo(a, b=3, *args, **kwargs):
Run Code Online (Sandbox Code Playgroud)

现在,b如果将其作为关键字参数或第二个位置参数传递,将显式设置.

例子:

foo(x) # a=x, b=3, args=(), kwargs={}
foo(x, y) # a=x, b=y, args=(), kwargs={}
foo(x, b=y) # a=x, b=y, args=(), kwargs={}
foo(x, y, z, k) # a=x, b=y, args=(z, k), kwargs={}
foo(x, c=y, d=k) # a=x, b=3, args=(), kwargs={'c': y, 'd': k}
foo(x, c=y, b=z, d=k) # a=x, b=z, args=(), kwargs={'c': y, 'd': k}
Run Code Online (Sandbox Code Playgroud)

请注意,特别是,foo(x, y, b=z)因为b在这种情况下按位置分配,所以不起作用.


此代码也适用于Python 3.把默认的ARG *args在Python 3使它能够在"关键字只"的说法只能通过名字来指定,而不是位置.如果你想在Python 2中使用仅限关键字的参数,你可以使用@ mgilson的解决方案.

  • 但这不适用于:`a = foo(1,2,3,4,5,b = 7)` (12认同)
  • 你也不能单独留下一个默认参数,同时也填写`*args`,no.这就是将功能添加到Python 3的原因.通常,Python 2中的默认参数被指定为明显类似于0或"无"的东西,以便可以显式传入它们. (5认同)

mgi*_*son 53

另一个问题的语法只是python3.x,并指定仅关键字参数.它不适用于python2.x.

对于python2.x,我想pop用kwargs:

def func(arg1, arg2, *args, **kwargs):
    opt_arg = kwargs.pop('opt_arg', 'def_val')
Run Code Online (Sandbox Code Playgroud)


Rom*_*man 6

与@yaccob 类似的方法,但清晰简洁:

Python 3.5或更高版本中:

def foo(a, b=3, *args, **kwargs):
  defaultKwargs = { 'c': 10, 'd': 12 }
  kwargs = { **defaultKwargs, **kwargs }
  print(a, b, args, kwargs)
  
  # Do something    

foo(1) # 1 3 () {'c': 10, 'd': 12}
foo(1, d=5) # 1 3 () {'c': 10, 'd': 5}
foo(1, 2, 4, d=5) # 1 2 (4,) {'c': 10, 'd': 5}
Run Code Online (Sandbox Code Playgroud)

注意:您可以在Python 2 中使用

kwargs = merge_two_dicts(defaultKwargs, kwargs)
Run Code Online (Sandbox Code Playgroud)

Python 3.5 中

kwargs = { **defaultKwargs, **kwargs }
Run Code Online (Sandbox Code Playgroud)

Python 3.9 中

kwargs = defaultKwargs | kwargs  # NOTE: 3.9+ ONLY
Run Code Online (Sandbox Code Playgroud)


Dan*_*ico 5

你也可以使用这样的装饰器:

import functools
def default_kwargs(**defaultKwargs):
    def actual_decorator(fn):
        @functools.wraps(fn)
        def g(*args, **kwargs):
            defaultKwargs.update(kwargs)
            return fn(*args, **defaultKwargs)
        return g
    return actual_decorator
Run Code Online (Sandbox Code Playgroud)

然后就这样做:

@default_kwargs(defaultVar1 = defaultValue 1, ...)
def foo(*args, **kwargs):
    # Anything in here
Run Code Online (Sandbox Code Playgroud)

例如:

@default_kwargs(a=1)
def f(*args, **kwargs):
    print(kwargs['a']+ 1)

f() # Returns 2
f(3) # Returns 4
Run Code Online (Sandbox Code Playgroud)