最近在写代码时发现一个有趣的地方,当python中的函数使用list作为默认参数且调用时不给其赋值时,无法通过在函数中将其赋值为[]来达到清空此默认参数的目的。按照道理来说,函数f1中的list为局部变量,在下次进入时,其应保持默认值才对。而且list具有可变性,在原内存地址中修改其内容。
具体代码如下:
def f1(a=[2]): a.append(100) print a a=[] #del a[:] print a def f2(a=[2]): a.append(100) print a #a=[] del a[:] print a def f3(b): b.append(100) print b b=[] print b print 'f1 result:' for i in range(2): f1() print 'f1 result when give parameter:' for i in range(3): c=[9] f1(c) print 'f2 result:' for i in range(4): f2() print 'f3 result:' for i in range(5): d=[8] f3(d)
运行结果如下:
f1 result: [2, 100] [] [2, 100, 100] [] f1 result when give parameter: [9, 100] [] [9, 100] [] [9, 100] [] f2 result: [2, 100] [] [100] [] [100] [] [100] [] f3 result: [8, 100] [] [8, 100] [] [8, 100] [] [8, 100] [] [8, 100] []
自己想了个可能的答案。(当python中的函数使用list作为默认参数且调用时不给其赋值时)在f1()中,list a在内存空间中指向[2]。执行a.append(100)后,list a指向的内存空间不变,内容变为[2,100]。执行a=[]后,list a指向的空间变了,其内容为[]。当再次进入f1()时,list a又指向了原来的内容空间,即内容为[2,100]。所以,当执行a.append(100)后,list a指向的内存空间不变,内容变为[2,100,100]。为了验证我的猜想,修改了下代码:
def f1(a=[2]): a.append(100) print a, print id(a) a=[] #del a[:] print a, print id(a) def f2(a=[2]): a.append(100) print a, print id(a) #a=[] del a[:] print a, print id(a) def f3(b): b.append(100) print b, print id(b) b=[] print b, print id(b) print 'f1 result:' for i in range(2): f1() print 'f1 result when give parameter:' for i in range(3): c=[9] f1(c) print 'f2 result:' for i in range(4): f2() print 'f3 result:' for i in range(5): d=[8] f3(d)
结果为:
f1 result: [2, 100] 12299240 [] 12338960 #the address is different [2, 100, 100] 12299240 [] 12338960 f1 result when give parameter: [9, 100] 12338960 [] 12339040 [9, 100] 12339040 [] 12338960 [9, 100] 12338960 [] 12339040 f2 result: [2, 100] 12299320 [] 12299320 #the address is the same [100] 12299320 [] 12299320 [100] 12299320 [] 12299320 [100] 12299320 [] 12299320 f3 result: [8, 100] 12339040 [] 12337280 [8, 100] 12337280 [] 12339040 [8, 100] 12339040 [] 12337280 [8, 100] 12337280 [] 12339040 [8, 100] 12339040 [] 12337280