关于Python中可变序列的那些坑
好像很多大厂面试题都有这个
如果函数默认参数可变,多次调用后结果如何?
先定义一个函数,传入一个 list,添加一个I再返回:
def add_i(my=[]):
my.append('I')
return my
当你正常传参调用时,结果好像对的:
>>> add_i([1, 2, 3])
[1, 2, 3, 'I']
>>> add_i(['x', 'y', 'z'])
['x', 'y', 'z', 'I']
当你使用默认参数调用时,一开始结果也是对的:
>>> add_end()
['I']
但是,再次调用add_end()时,结果就不对了:
>>> add_end()
['I', 'I']
>>> add_end()
['I', 'I', 'I']
很多人很疑惑,默认参数是[],但是函数似乎每次都“记住了”上次添加了’I’后的 list。
如果你每次调用id()就会明白,每次地址都一样
print(id(add_i()))
print(add_i())
4809352
['I', 'I']
print(id(add_i()))
print(add_i())
4809352
['I', 'I', 'I', 'I']
print(id(add_i()))
print(add_i())
4809352
['I', 'I', 'I', 'I', 'I', 'I']
原因解释如下:
Python 中可变序列,所有元素都储存在同一个地址中
函数在定义的时候,默认参数如果为可变序列
那多次调用,默认参数都为第一次调用的可变序列,都存储在同一个地址
定义默认参数要牢记一点:默认参数必须指向不变对象!
要修改上面的例子,我们可以用None这个不变对象来实现:
def add_end(L=None):
if L is None:
L = []
L.append('I')
return L
现在,无论调用多少次,都不会有问题:
>>> add_end()
['I']
>>> add_end()
['I']