Skip to main content
 首页 » 编程设计

不可变默认参数值的 Python 行为

2025年05月04日17linjiqin

>>> 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 .