今天在码python的时候遇到灵异事件,查阅python官方文档后发现原来python的形参列表默认值有个很值得注意的地方:
默认参数在函数初始化的时候默认值就被赋值,因此如果参数默认值为变量,则变量值在初始化函数时就被确认下来。
默认形参是普通变量
下面这个例子很好理解:
i = 5
def f(arg=i):
print arg
i = 6
f()
由于参数在初始化的时候默认值被赋值为5,后面再修改i,不会再影响这个形参的默认值了。
所以将打印输出5,而不是6。
默认形参是对象实例
我们知道,赋值对象实例其实传递的是实例的内存地址,那这种情况下,改变这个对象实例将影响函数的执行结果。
把上面的默认形参改为一个list(python的list也是一种对象)。
i = [5]
def f(arg=i):
print arg
i[0] = i[0] + 1
f()
这个执行结果是[6]。
甚至,在函数内部对这个默认形参的操作,也会被带到下一次执行中。
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
执行结果:
[1]
[1, 2]
[1, 2, 3]
因此,官方建议一种更好的写法,来规避这个问题。
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
其实这个做法是说,当需要给一个形参做默认值,而且这个默认值是一个对象实例的时候,应该把赋值的工作放在函数内部,而不要写到函数定义的参数列表中。
网友评论