有没有一种方法可以通过两个函数传递可选参数?

4

问题“有没有一种方法可以向函数传递可选参数?”描述了如何使用默认关键字参数。

我有两个函数,其中一个调用另一个函数,并且我想能够检测外部函数是否使用可选参数进行调用:

def foo(x1, opt=None):
    bar(opt)

def bar(opt=5):
    print opt

if __name__ == '__main__':
    foo(1)           # Should print 5, actually prints None
    foo(2, opt=3)    # Does print 3

这将打印:

None
3

Foo()可以编写特殊逻辑来检测可选参数是否传递,但是否有一种Pythonic方式可以传递保留其可选性的可选参数而不使用额外的逻辑?

def foo2(x1, opt=None):
    if opt is None:
        bar()
    else:
        bar(opt)

默认值必须在内部函数中定义,因为它可能会直接被调用。我也可以为内部和外部函数定义相同的默认值,但是当默认值比整数更复杂时,这样做有点丑陋(违反DRY原则)。


1
我只是在思考一个问题:如果你需要为内部和外部函数定义两个不同的默认值,那么你是否有一个设计问题? - tangoal
这个有帮助吗:https://docs.python.org/3/faq/programming.html#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another - KolaB
我认为如果您重新构造代码,使用有意义的函数和参数名称而不是 foox1opt 等,来解释上下文,这将会有所帮助。我确实理解您的要求,但是如果不了解您试图解决的实际问题,很难提供意见。 - NPE
@NPE,无意义的名称是重现问题的最简单方法。实际用例是内部函数根据一些参数生成(非常长的)字符串,并且外部函数根据这些参数加上文件名写入包含该输出的文件中。更具体地说,字符串/文件的内容是HTML5文档。 - Dave
5个回答

2

您可以使用 **kwargs 语法来允许传递任何关键字参数,如果有任何额外的关键字不起作用,则会引发错误(或者干脆忽略它们,尽管这会使用户感到困惑,因为他们可能会打错字并且没有出现错误)。在干净地忽略它们的情况下:

def foo(x1, **kwargs):
    if "opt" in kwargs:
        bar(kwargs["opt"])
    else:
        bar()

基本上,**kwargs 允许您传递任何关键字参数,如 foo(opt = 3) 并将它们全部放在一个字典中。但这种方法的缺点是您不能像 foo(3) 这样调用它。如果您想使用位置参数而不是关键字参数,请使用 *args,它会给出一个参数元组,但是您无法指定关键字调用它。很遗憾,这两者不能同时实现。

2
你不需要使用 **kwargs;可以使用 if opt is None: bar() else bar(opt) - chepner
@chepner 我的解决方案允许您以不同的含义调用foo(None)foo() - hyper-neutrino
1
我担心就是这样,但只是想确认没有可用的魔法酱。谢谢。 - Dave
很抱歉,Dave。我认为在Python中无法使用反射方式来实现。 - hyper-neutrino

1
也许可以在两个地方都设置默认参数:
DEFAULT_OPT = 5

def foo(x1, opt=DEFAULT_OPT):
    bar(opt)

def bar(opt=DEFAULT_OPT):
    print opt 

否则使用kwargs,但我通常避免使用它,因为很难维护:
def foo(x1, **kwargs):
    bar(**kwargs)

def bar(opt=5, **_):
    print opt 

1

由于未指定opt,它默认为None,正如您所见。这为opt提供了定义,并且它不会记住或保留任何默认值的属性,因此,在此处实现逻辑是必需的以获得所需的结果。


0
foo 中,你使用 opt 调用了 bar。这将覆盖 bar 内部的默认值 opt

是的,这就是发生的事情。我相信 OP 知道这一点,并且正在询问如何避免这种情况... - hyper-neutrino

0

在Python中,None是一个对象(请参见这里)。这意味着当您将None传递给bar时,它是有效的参数。这就是为什么它不会触发默认参数值5的原因。我不知道Python中还有什么其他东西可以做到这一点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接