在Python中,如果你直接将可变类型作为默认参数,那么就会出现众所周知的边际情况:
def foo(x=[]): return x
y = foo()
y.append(1)
print foo()
通常的解决方法是将参数默认值设置为
None
,然后在函数体中进行设置。但是,有3种不同的方法来实现这一点,其中2种基本相同,但第三种方法则完全不同。def foo(x=None):
if x is None:
x = []
return x
这是我通常看到的。
def foo(x=None):
x = [] if x is None else x
return x
在语义上完全相同。有一行代码更短,但有些人抱怨Python的三元运算符不太自然,因为它没有以条件开头,建议避免使用。
def foo(x=None):
x = x or []
这是最简洁的方法。今天我才了解到这种疯狂的方法。我懂Lisp,所以这对我来说可能比一些Python程序员更少令人惊讶,但我从未想过这在Python中会奏效。这种行为有所不同;如果你传递的值不是None
,但求值结果为False(例如False
),它将不会覆盖默认值。如果默认值不会求值结果为false,它无法使用,因此如果你有一个非空列表或字典作为默认值,它就不能使用。但在我的经验中,空列表/字典是感兴趣的情况的99%。
关于哪种方法最符合Python风格,有何想法?我知道这其中有一些主观因素,但我希望有人能给出一个好的例子或理由,说明哪种方法被认为是最惯用的。与大多数社区不同,Python通常强烈鼓励人们按照某种方式做事情,因此我希望这个问题及其答案即使不是完全黑白分明,也会有所裨益。
x = A或B
来创建三元语句被认为是不好的做法...尽管如此,你可以这样做...但我会 主张 Python三元语句(选项B)是最具Python风格的...但我很确定这个问题将会被关闭,因为它并不适合在SO上进行讨论(SO讨厌“意见”,更喜欢“事实”)。 - Joran Beasleydef foo(**kwargs): return kwargs.get('x', [])
。 - marcelm**kwargs
对调用者的行为完全不同,它允许传递随机参数。显然,除非你要转发到另一个函数或确实打算使用所有参数,否则不应使用**kwargs
。感谢你提醒我明确地传递x=[]
,我没有想到这一点。 - Nir Friedmanif x is None: x = []
,那么第二个版本甚至不会比它“短一行”。 - Peter Hansen