如果可选参数为 None,则调用不带可选参数的函数

新手上路,请多包涵

有一个函数接受可选参数。

 def alpha(p1="foo", p2="bar"):
     print('{0},{1}'.format(p1, p2))

让我重复一下当我们以不同方式使用该函数时会发生什么:

 >>> alpha()
foo,bar
>>> alpha("FOO")
FOO,bar
>>> alpha(p2="BAR")
foo,BAR
>>> alpha(p1="FOO", p2=None)
FOO,None

现在考虑我想调用它的情况 alpha("FOO", myp2)myp2 将包含要传递的值,或者是 None 但即使该函数处理 p2=None ,我还是希望它使用其默认值 "bar" 代替。

也许这样的措辞令人困惑,所以让我重新措辞:

如果 myp2 is None ,调用 alpha("FOO") 。否则,调用 alpha("FOO", myp2)

区别是相关的,因为 alpha("FOO", None) 的结果与 alpha("FOO") 不同。

我怎样才能简洁地(但可读地)做出这种区分?

一种可能性通常是 alpha 中检查 None ,我们鼓励这样做,因为这会使代码更安全。但是假设 alpha 被用在它实际应该处理 None 的其他地方。

我想在调用者端处理它

一种可能性是区分大小写:

 if myp2 is None:
    alpha("FOO")
else:
    alpha("FOO", myp2)

但是当有多个这样的参数时,这很快就会变成很多代码。 (指数,2^n)

另一种可能性是简单地做 alpha("FOO", myp2 or "bar") ,但这 _需要我们知道默认值_。通常,我可能会采用这种方法,但稍后我可能会更改 alpha 的默认值,然后需要手动更新此调用以便仍然使用(新)默认值调用它.

我使用的是 python 3.4,但最好是您的答案可以提供适用于任何 python 版本的好方法。


这个问题在技术上已经在这里完成了,但我再次改写了一些要求,因为第一个答案确实掩盖了这一点:

我希望 alpha 的行为及其默认值 "foo", "bar" 一般保留,所以它(可能)不是更改的选项 alpha

再换句话说,假设 alpha 在其他地方被用作 alpha("FOO", None) 其中输出 FOO,None 是预期的行为。

原文由 lucidbrot 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 536
2 个回答

从字典中将参数作为 kwargs 传递,从中过滤出 None 值:

 kwargs = dict(p1='FOO', p2=None)

alpha(**{k: v for k, v in kwargs.items() if v is not None})

原文由 deceze 发布,翻译遵循 CC BY-SA 4.0 许可协议

但是假设 alpha 用于其他实际应该处理 None 的地方。

为了回应这个问题,我已经知道有一个 None 的值实际上不是 None 用于这个确切的目的。

 _novalue = object()

def alpha(p1=_novalue, p2=_novalue):
    if p1 is _novalue:
        p1 = "foo"
    if p2 is _novalue:
        p2 = "bar"
    print('{0},{1}'.format(p1, p2))

现在参数仍然是可选的,所以你可以忽略传递它们中的任何一个。并且函数处理 None 正确。如果您想 明确 不传递参数,可以传递 _novalue

 >>> alpha(p1="FOO", p2=None)
FOO,None
>>> alpha(p1="FOO")
FOO,bar
>>> alpha(p1="FOO", p2=_novalue)
FOO,bar

并且由于 _novalue 是为此 明确 目的创建的特殊虚构值,任何通过 _novalue 的人肯定是打算“默认参数”行为,而不是通过 None 谁可能打算将值解释为文字 None

原文由 Silvio Mayolo 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题