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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15301999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:43:38  来源:igfitidea点击:

Default arguments with *args and **kwargs

pythonpython-2.7

提问by

In Python 2.x(I use 2.7), which is the proper way to use default arguments with *argsand **kwargs?
I've found a question on SO related to this topic, but that is for Python 3:
Calling a Python function with *args,**kwargs and optional / default arguments

Python 2.x(我使用 2.7)中,这是使用带有*args和的默认参数的正确方法**kwargs吗?
我发现了一个与此主题相关的 SO 问题,但这是针对Python 3 的
使用 *args、**kwargs 和可选/默认参数调用 Python 函数

There, they say this method works:

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

def func(arg1, arg2, *args, opt_arg='def_val', **kwargs):
    #...

In 2.7, it results in a SyntaxError. Is there any recommended way to define such a function?
I got it working this way, but I'd guess there is a nicer solution.

在 2.7 中,它导致SyntaxError. 有没有推荐的方法来定义这样的函数?
我以这种方式工作,但我想有一个更好的解决方案。

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

采纳答案by nneonneo

Just put the default arguments before the *args:

只需将默认参数放在*args

def foo(a, b=3, *args, **kwargs):

Now, bwill be explicitly set if you pass it as a keyword argument or the second positional argument.

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

Examples:

例子:

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}

Note that, in particular, foo(x, y, b=z)doesn't work because bis assigned by position in that case.

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



This code works in Python 3 too. Putting the default arg after*argsin Python 3 makes it a "keyword-only" argument that can onlybe specified by name, not by position. If you want a keyword-only argument in Python 2, you can use @mgilson's solution.

此代码也适用于 Python 3。在 Python 3中将默认 arg 放在后面*args使其成为“仅关键字”参数,只能按名称指定,而不能按位置指定。如果您想在 Python 2 中使用仅关键字参数,您可以使用 @mgilson 的解决方案。

回答by mgilson

The syntax in the other question is python3.x only and specifies keyword only arguments. It doesn't work on python2.x.

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

For python2.x, I would popit out of kwargs:

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

def func(arg1, arg2, *args, **kwargs):
    opt_arg = kwargs.pop('opt_arg', 'def_val')

回答by conner.xyz

Another way to handle with Python 2.x:

另一种处理 Python 2.x 的方法:

def foo(*args, **kwargs):
    if 'kwarg-name' not in kwargs.keys():
        kwargs['kwarg-name'] = 'kwarg-name-default-value'
    return bar(*args, **kwargs)

This handles passing arbitrary *argsto the underlying call unlike @nneonneo's answer.

*args与@nneonneo 的回答不同,这处理将任意传递给底层调用。

回答by yaccob

Sticking quite close to your solution approach while trying to make it more generic and more compact I would suggest to consider something like this:

在尝试使其更通用和更紧凑的同时,非常接近您的解决方案方法,我建议考虑这样的事情:

>>> def func(arg1, arg2, *args, **kwargs):
...     kwargs_with_defaults = dict({'opt_arg': 'def_val', 'opt_arg2': 'default2'}, **kwargs)
...     #...
...     return arg1, arg2, args, kwargs_with_defaults

>>> func('a1', 'a2', 'a3', 'a5', x='foo', y='bar')
('a1', 'a2', ('a3', 'a5'), {'opt_arg2': 'default2', 'opt_arg': 'def_val', 'y': 'bar', 'x': 'foo'})

>>> func('a1', 'a2', 'a3', 'a5', opt_arg='explicit_value', x='foo', y='bar')
('a1', 'a2', ('a3', 'a5'), {'opt_arg2': 'default2', 'opt_arg': 'explicit_value', 'y': 'bar', 'x': 'foo'})

回答by Daniel Américo

You could also use a decorator like this:

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

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

Then just do:

然后就这样做:

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

For instance:

例如:

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

f() # Returns 2
f(3) # Returns 4