Python 可变范围,不可变与可变,以+=

Python 可变范围,不可变与可变,以+=,python,python-3.x,Python,Python 3.x,这是我们的后续问题 案例1,以下代码 a = 0 def test_immutable(): a += 1 test_immutable() array = [0, 0, 0] def test_mutable(): array[0] += 1 test_mutable() print(array) 遇到错误: UnboundLocalError: local variable 'a' referenced before assignment 对原始帖子的回答很好地解释了第

这是我们的后续问题

案例1,以下代码

a = 0
def test_immutable():
    a += 1
test_immutable()
array = [0, 0, 0]
def test_mutable():
    array[0] += 1
test_mutable()
print(array)
遇到错误:

UnboundLocalError: local variable 'a' referenced before assignment
对原始帖子的回答很好地解释了第一个案例
a+=1
进行赋值,从而使
a
成为尚未与任何对象赋值的局部变量,因此引用它会导致
UnboundLocalError

在下面的第二个示例中,当我将
a
替换为
array[0]
时,它在没有
UnboundLocalError
的情况下工作

案例2,以下代码

a = 0
def test_immutable():
    a += 1
test_immutable()
array = [0, 0, 0]
def test_mutable():
    array[0] += 1
test_mutable()
print(array)
输出

[1, 0, 0]

我想这与
a
是不可变的,而
array
是可变的有关。但是Python究竟是如何区别对待这两种情况的呢?我很困惑。

您观察到的问题实际上与可变或不可变类型无关,它是一个范围问题

考虑以下几点:

a=0
a+=1
尽管
0
是不可变的,但这仍然有效

此外,这:

array=[0,0,0]
def test_mutable():
数组+=[1]
测试_可变()
打印(数组)
是否向您抛出相同的
UnboundLocalError

问题在于范围界定。当你试图在函数中重复使用
a
时,解释器会对你所指的
a
感到困惑,因为它首先意识到无论你想计算什么,你都想把它命名为
a
,所以它会为你保留本地名
a
,覆盖全局名
a
,但是当您尝试将它用于
+=1
位时,它意识到没有任何东西绑定到本地
a


使用
数组
,尤其是
数组[0]
时,情况有所不同,因为您没有保留名称
数组
,以供本地使用,而是在函数中更新全局变量时,继续使用全局数组

,它应该被明确地声明为全局的,这样就可以了

a = 0
def test_immutable():
    global a
    a += 1
test_immutable()
因此,当您得到一个错误时,它假设
a
是一个局部变量,但在更新它之前没有声明,即
a+=1
。如果不更新函数中的全局变量,则可以使用该全局变量,而无需显式将其声明为全局变量。例如:

a = 0
def test_immutable():
    print(a)
test_immutable()
对于列表,您不是更新整个列表,而是更新其中的一个元素。因此,它应该在不明确声明为全局的情况下工作

如果您尝试以下方法:

a = [1, 2, 3]
def test_immutable():
    a = [1, 4, 3]
test_immutable()
print(a)
a = [1, 2, 3]
def test_immutable():
    global a
    a = [1, 4, 3]
test_immutable()
print(a)
输出将是
[1,2,3]
,因为数组正在本地引用中更新。但是,如果您尝试以下操作:

a = [1, 2, 3]
def test_immutable():
    a = [1, 4, 3]
test_immutable()
print(a)
a = [1, 2, 3]
def test_immutable():
    global a
    a = [1, 4, 3]
test_immutable()
print(a)

输出将是
[1,4,3]
,因为值在全局引用中得到更新,并且没有任何错误

这不是易变性的问题,而是您没有将名称
数组
重新绑定到其他内容<代码>数组在函数之前、期间和之后指向同一对象。如果您尝试:
array+=[1]
您也会遇到同样的错误。正如一般所说,在您对变量绑定的规则有了良好的感觉之前,这些规则是非常混乱的,但我保证,一旦您玩得够多,它就会自然而然地出现。很好的解释。谢谢你,诺洛克。我接受了你的回答。