python - 为什么可以在没有全局指定的情况下扩展修改值?

时间:2012-11-24 19:32:38

标签: python

>>> x = []
>>> y = [1,2,3]
>>> def func1(L):
...     x+=L
... 
>>> def func2(L):
...     x.extend(L)
... 
>>> func1(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in func1
UnboundLocalError: local variable 'x' referenced before assignment
>>> func2(y)
>>> x
[1, 2, 3]

为什么列表extend()方法可以改变非全局变量,但+ =运算符不能?据我所知,只要函数没有赋值变量,它就可以在没有全局指定的情况下读取它。但在这种情况下,函数会设置值。

1 个答案:

答案 0 :(得分:5)

它不设置值,它会修改现有值。在Python中,将名称绑定到值是一回事,修改(或改变)值是另一回事。

真正的问题是为什么+= 不能工作,因为对于列表,此操作被定义为也就地修改列表。答案就是这样,因为该运算符看起来像赋值,所以决定使它像作用域和绑定目的一样。 The documentation说(重点补充):

  

增强赋值评估目标(与正常赋值语句不同,它不能是解包)和表达式列表,执行特定于两个操作数上的赋值类型的二进制运算,以及将结果分配给原始目标

换句话说,扩充分配包括作为操作一部分的赋值,因此适用正常的作用域/绑定规则。由于目标被评估为目标,如果它是一个函数,它被视为局部变量。因此,当x是列表时,x += newList实际上就像:

x.extend(newList)
x = x

更一般地说,扩充赋值可以就地修改操作数,但它仍然会尝试将结果值重新绑定到原始变量。所以x += other的工作原理如下:

y = x.__iadd__(other)
x = y