PEP8: B006 Do not use mutable data structures for argument defaults.
该场景下会导致函数的结果与预期不符
错误示范:
def append(element, seq=[]):
seq.append(element)
return seq
>>> append(1) # seq 的默认值是 []
[1] # 返回值正常
>>> append(2) # => seq 的默认值变成了 [1]
[1, 2] # 返回值异常
正确使用示例:
def append(element, seq=None):
if seq is None: # 👍
seq = []
seq.append(element)
return seq
>>> append(1) # `seq` is assigned to []
[1]
>>> append(2) # `seq` is assigned to [] again!
[2] # 正确的返回预期的数值
这种现象的原因在 Python 常见疑难问题 中有描述
Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.
参数默认值不过是一个指向那个在compile
阶段就已经存在的对象的指针, 如果调用函数时,没有显示指定传入参数值得话。那么所有这种情况下的该参数都会作为编译时创建的那个对象的一种别名存在。如果参数的默认值是一个不可变(Imuttable)
数值,那么在函数体内如果修改了该参数,那么参数就会重新指向另一个新的不可变值。而如果参数默认值是和本文最开始的举例一样,是一个可变对象(Muttable)
,那么情况就比较糟糕了。所有函数体内对于该参数的修改,实际上都是对compile
阶段就已经确定的那个对象的修改。
Python官方文档中也有特别提示
Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes.
参考文档:
https://florimond.dev/en/posts/2018/08/python-mutable-defaults-are-the-source-of-all-evil/
https://docs.python.org/3/tutorial/controlflow.html#more-on-defining-functions
https://docs.python-guide.org/writing/gotchas/