Python3中的默认函数可变问题

1
2
3
4
5
6
7
8
9
10
11
from datetime import datetime
from time import sleep


def f(l=[]):
l.append('a')
print(datetime.now())
return l


print(f(), sleep(2), f())

光看代码的话大家会觉得是什么输出呢?

1
2
3
2020-03-26 21:19:36.722671
2020-03-26 21:19:38.722719
['a', 'a'] None ['a', 'a']

是不是和预期的不太一样?这是因为Python在处理默认参数时,仅在该函数定义的时候,被赋值一次。
这也就导致了后续的默认参数操作会对最开始的默认参数可变对象进行操作。

1
2
3
4
5
6
7
8
9
10
11
from datetime import datetime
from time import sleep


def f(l=[], time=datetime.now()):
l.append('a')
print(time)
return l


print(f(), sleep(2), f())

这里的输出就会导致于预期的不一致,原本打算让函数调用时对其生成时间,然而输出却是。

1
2
3
2020-03-26 21:25:55.973219
2020-03-26 21:25:55.973219
['a', 'a'] None ['a', 'a']

也恰恰证明了Python在处理默认参数时,仅在该函数定义的时候,被赋值一次。
顺带print函数会对内含的函数全部处理完后输出,也就是上面的输出,即使有sleep,输出的结果仍然是最终处理的。
要避免上面的错误发生,Pycharm会做出提醒使用不可变对象的Warning,实际操作只需要对其做一个判断即可,例如。

1
2
3
4
5
6
7
8
9
10
def f(l=None):
if l is None:
l = []
l.append('a')
return l


print(f(), f())

# ['a'] ['a']