听到这个解释,豁然开朗,解释器试验如下:
点击(此处)折叠或打开
-
>>> def f(x = []):
-
print(id(x))
-
x.append(1)
-
print x
-
print(id(x))
-
-
-
>>> f()
-
38869952 # 可变默认参数是在原地更改!!!
-
38869952
-
>>> f()
-
38869952 # 再次调用时,可变默认参数还是引用最初定义的!!!
-
38869952
-
# 注意,默认参数是在定义时赋值,且仅仅赋值一次。
-
# 当函数多次被调用,并且没有提供默认的参数值,就会从定义时赋值的地方取得值!
-
# 即使函数中给默认参数重新赋值了,下次调用还是会从定义赋值的地方取得值!
-
# 如以下的示例:当f2()多次调用,虽然在函数体里面给y重新赋值了,但是下次调用时
-
# 再次打印print id(x) 的结果也还是一样的!
-
# 所以:
-
# 1. 假如默认参数是可变对象,则会在原处直接更改对象,下次调用参数时,默认参数已经
-
# 更改过的了。如f()函数。
-
# 2. 假如默认参数不可变,那么给函数中给 参数赋值时,参数会引用内存的其他地方。下次函数调用时
-
# 默认参数还是从定义时赋值处取得值,因此没有副作用!
-
>>> def f2(y = None):
-
print(id(y))
-
if not y:
-
y = []
-
y.append(1)
-
print(id(y))
-
-
-
>>> f2()
-
505672708 # 定义时默认参数引用这一块内存。
-
38888872 # 函数体内赋值后,y引用其他地方。
-
>>> f2()
-
505672708 # 再次调用,y还是引用定义时赋值的内存处。
-
43910728 # 函数体内赋值后,y引用其他地方。
-
>>> f()
-
38869952
-
38869952
-
>>> f2()
-
505672708
-
43909408
-
>>> f2()
-
505672708
-
38868752
- >>>