有一个带有可选参数的函数 .
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为None,则调用alpha(“FOO”) . 否则,调用alpha(“FOO”,myp2) .
区别是相关的,因为 alpha("FOO", None)
的结果与 alpha("FOO")
不同 .
How can I concisely (but readably) make this distinction?
一种可能性通常是check for None within alpha,这将被鼓励,因为这将使代码更安全 . 但是假设 alpha
用于实际上应该处理 None
的其他地方 .
I'd like to handle that on the caller-side .
一种可能性是区分案例:
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
是预期的行为 .
6 回答
将参数作为kwargs从字典中传递出来,从中过滤出
None
值:感谢你的回答,我想我会尽力做到这一点:
这可能并不完美,但似乎有效:它是's a function that you can call with another function and it'的参数,它应用deceze's answer来过滤掉
None
的参数 .为了回应这个问题,我知道有一个类似
None
的值,实际上并不是None
.现在参数仍然是可选的,所以你可以忽略它们中的任何一个 . 并且该函数正确处理
None
. 如果您希望显式不传递参数,则可以传递_novalue
.并且由于
_novalue
是为此明确目的而创建的特殊组合值,任何通过_novalue
的人肯定打算"default argument"行为,而不是通过None
的人可能打算将该值解释为文字None
.不幸的是,没有办法做你想做的事 . 即使广泛采用的python库/框架也使用您的第一种方法 . 这是一行额外的代码,但它非常易读 .
不要使用
alpha("FOO", myp2 or "bar")
方法,因为正如你自己提到的那样,它会产生一种可怕的耦合,因为它需要调用者知道有关函数的细节 .关于解决方法:您可以为您创建一个装饰器(使用
inspect
模块),它会检查传递给它的参数 . 如果其中一个是None
,它将使用其自己的默认值替换该值 .您可以通过
alpha.__defaults__
检查默认值,然后使用它们而不是None
. 这样你就可以绕过默认值的硬编码:我很惊讶没有人提起这件事
您将“无”分配给p2作为标准(或者不是,但这样您在代码中的某一点上具有真正的标准)并使用内联if . Imo最狡猾的答案 . 想到的另一件事是使用包装器,但这样会更不易读 .
编辑:我可能会做的是使用虚拟值作为标准值并检查它 . 所以这样的事情:
生产环境 :