L=[ ]
在下面这段代码中,函数f1的默认参数L=[ ]
def f1(a, L=[]):
L.append(a)
return L
print(f1(1))
print(f1(2))
print(f1(3))
运行代码,输出为
[1]
[1, 2]
[1, 2, 3]
L=None
在下面这段代码中,函数f2的默认参数L=None
def f2(a, L=None):
if L is None:
L = []
L.append(a)
return L
print(f2(1))
print(f2(2))
print(f2(3))
运行代码,输出为
[1]
[2]
[3]
解析
首先必须明确在python中所有的变量都是一个引用,引用保存的是对象的地址。比如 a=1 这个表达式做了两件事情,
1、创建一个对象,将1保存到这个对象中
2、将该对象的地址赋值给a。
这样一来,a就是一个引用,该引用保存的是新创建对象的地址。
又因为函数的默认参数只能在编译阶段被赋值,赋值完成后每次调用函数该参数都将以该值执行。所以f1和f2的默认参数L都在编译阶段有了默认值,f1的L保存的是 [] 的地址,f2的L保存的是None的地址(也就是没有地址,即L没有保存任何值)。
当执行f1中的代码时,由于列表是可变数据类型,在函数中对L指向的对象的内容进行了修改,但L并没有改变,L中保存的依旧是原来那个对象的地址。
而在f2中,L一开始并不指向任何对象(L=None),执行过程中又指向了一个列表对象(L=[ ]),每次执行函数时默认参数只能取None,这就导致L每次都会从None变为指向一个新的列表对象,这个过程产生3个新的列表对象,每个列表对象中存储着一个不同的值,分别是[1], [2], [3]
要点
这个问题中需要掌握的要点有两个,分别是
1.python中的变量都是引用,引用保存的是一个地址,该地址指向某个对象。
2.函数的默认参数在编译阶段被赋值,之后每次调用函数时对应的默认参数值任为第一次被赋予的值。
f1中的L始终指向同一个对象(只是对象的内容发生了更改),f2中的L每次调用时都会被重置为None,在函数体中又会被修改。