>>> def a():
... print "a executed"
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print x
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
x 在第一次定义函数 b 时绑定(bind)到一个空列表对象。每次调用 b 时都会修改空列表对象,因为 b 已绑定(bind)到该对象。
我不明白的是,当这种情况发生在不可变对象(immutable对象)上时:
>>> def a():
... print "a executed"
... return 0
...
>>>
>>> def b(x=a()):
... x = x + 2
... print x
...
a executed
>>> b()
2
>>> b()
2
从我的 POV 来看,当第一次定义函数 b 时,x 绑定(bind)到 int 对象 0。然后,在调用 b() 时修改 x。因此,对 b() 的后续调用应将 x 重新绑定(bind)到 2、4、6 等。为什么不发生这种情况?我显然在这里遗漏了一些重要的东西!
谢谢 :)
请您参考如下方法:
当您执行 x = 时,您并没有修改 x 引用的对象,您只是将引用 x 更改为指向到不同的对象,在本例中是另一个 int。在这种情况下,x 是否指向不可变对象(immutable对象)与事件无关。如果您对列表执行 x = x + [5],它也将保持不变。注意区别:
def b1(x = []):
x = x + [5]
print(x)
def b2(x = []):
x.append(5)
print(x)
print("b1:")
b1()
print("b1:")
b1()
print("b2:")
b2()
print("b2:")
b2()
给予:
b1:
[5]
b1:
[5]
b2:
[5]
b2:
[5, 5]
当函数被执行时,您正在处理一个局部变量 x,它要么使用默认值初始化,要么由调用者提供。所以反弹的是局部变量x,而不是参数的默认值。
您可能还想了解正式 和实际 参数之间的区别。它与这个问题只有轻微的关系,但可能会帮助您更好地理解这一点。可以找到示例说明 here .
