【问题标题】:How to use default arguments in a function call with *args and **kwargs?如何在带有 *args 和 **kwargs 的函数调用中使用默认参数?
【发布时间】:2018-10-18 13:03:22
【问题描述】:

我有以下简单的示例代码:

def wrapper(foo, para1=1, *args):
    print("para1: "+ str(para1))
    print(foo(*args))

def foo1(x):
    return 2*x

wrapper(foo1, 2, 3)

我定义了一个函数wrapper,它有一个参数para1,默认值1

但是为了正确调用带有函数foo1 的包装器,我必须一直设置para1,因为我必须将额外的参数传递给foo1。这意味着默认值para1=1 没有任何意义,因为无论如何我必须一直定义它。

或者有没有其他方法来定义函数,这样我就可以轻松使用这个默认值,而不必一直定义它?

例如,

wrapper(foo1, *args=(3,))
wrapper(foo=foo1, args=(3,))

不工作...

用例示例:

def wrapper(foo, timeout=10, *args):
    time0 = time.time()
    while time0 < time.time() + timeout:
        if foo(*args):
             return True
        time.sleep(1)
    raise SomeTimeout Exception

【问题讨论】:

  • 你不能把para1放在wrapper args的末尾吗?
  • 不,然后我得到一个语法错误
  • @Jean-FrançoisFabre 然后像wrapper(foo1, 2, 3) 这样的调用会中断
  • def wrapper(foo, *args, para1=1)又出了什么问题?

标签: python function default


【解决方案1】:

您以接受数字的方式定义了foo1 函数,但您尝试在wrapper 函数中将一个元组传递给它。 以下应该有效:

def wrapper(foo, para1=1, *args):
    print("para1: "+ str(para1))
    print(foo(*args))



def foo1(*x):
    return 2*x


wrapper(foo1, (2, 3))

foo1的定义中x改为*x

【讨论】:

  • @Idlehands,它有效!也许,错误来自其他地方。
  • 它没有。你真的测试过吗? SyntaxError: invalid syntax 是被提出来的。具体来说,*args=...是错误的来源。
  • @Idlehands,是的,我有!我用完整的代码更新了我的答案
  • 通过您的最新编辑,您又回到了 OP 的原点。如果你想在没有para1 的情况下调用包装器怎么办? wrapper(foo1, 3) 不起作用。解释器不知道第二个参数不存在。 3 在这种情况下是第二个参数。
  • @Idlehands,好的。我以错误的方式得到了这个问题。我更新了答案。
【解决方案2】:

把它变成这样怎么样?

#/usr/bin/env python3

def f1(f, *args, **kwargs):
    if not 'b' in kwargs:
        kwargs['b'] = 1
    print('b =',kwargs['b'])
    f(args)

def fx(args):
    print(args)

f1(fx, 3, 4)
print()
f1(fx, 3, 4, b=2)

输出:

b = 1                                                                     
(3, 4)

b = 2                                                                     
(3, 4)

【讨论】:

    【解决方案3】:

    编辑:既然您现在已经明确表示它适用于 Python 2,def wrapper(foo, *args, timeout=10) 会给您一个语法错误。所以请改用下面的方法。

    仅使用*args 我认为这不太可行。如果可能,请尝试改用**kwargs

    def wrapper(foo, *args, **kwargs):
        time0 = time.time()
        # define a default timeout period if not explicitly passed in by keyword
        timeout = kwargs.get('timeout') if 'timeout' in kwargs else 10
        while time0 < time.time() + timeout:
            if foo(*args):
                return True
            time.sleep(1)
        raise SomeTimeOut Exception
    

    每次你想明确地提供一个超时时间,这样调用它:

    wrapper(foo, 1, 2, 3, timeout=60)
    

    Test code:

    def wrapper(foo, *args, **kwargs):
        timeout = kwargs.get('timeout') if 'timeout' in kwargs else 10
        print 'Timeout = {0}'.format(timeout)
        foo(*args)
    
    def foo(*args):
        print 'Args = {0}'.format([a for a in args])
    
    wrapper(foo, 1, 2, 3, timeout=20)
    
    # Results
    # Timeout = 20
    # Args = [1, 2, 3]
    

    【讨论】:

    • 第二种方法至少应该适用于 Python 2。请再试一次。
    猜你喜欢
    • 2012-04-09
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多