在工作中不小心踩了一个关于python默认参数的坑,这里记录一下。
先看一下例子:
def fuc(data=[]):
data.append(1)
return data
print(fuc())
print(fuc())
print(fuc())
[1]
[1, 1]
[1, 1, 1]
{('a', 'b'): 1}
可以发现输出并不像我们想象中的都是[1],这是因为,调用fuc函数操作的都是同一个列表对象,因此我不停的调用fuc函数变成了往列表中追加元素。
造成这种现象的原因是,python函数在定义时,默认参数的值就被计算出来了,即[ ],因为默认参数data也是一个变量,它指向对象[ ],每次调用该函数,
如果改变了data的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[ ]了。
定义默认参数要牢记一点:默认参数必须指向不变对象!(也就是不要指向列表和字典)
要修改上面的例子,可以用None这个不变对象来实现:
def fuc(data=None):
if data is None:
data = []
data.append(1)
return data
print(fuc())
print(fuc())
print(fuc())
[1]
[1]
[1]
为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。因此,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。