Python变量范围,不可变vs可变,用+ =表示

时间:2019-07-13 22:41:50

标签: python python-3.x

这是对Python variable scope error

的跟进问题

case-1,以下代码

a = 0
def test_immutable():
    a += 1
test_immutable()

遇到错误:

UnboundLocalError: local variable 'a' referenced before assignment

原始帖子的答案很好地解释了第一种情况。 a += 1进行分配,因此使a为尚未分配任何对象的局部变量,因此引用它会导致UnboundLocalError

在下面的第二个示例中,当我将a替换为array[0]时,它可以不使用UnboundLocalError

情况2,以下代码

array = [0, 0, 0]
def test_mutable():
    array[0] += 1
test_mutable()
print(array)

输出

[1, 0, 0]

我猜想这与a是不可变的而array是可变的有关。但是,Python如何将这两种情况区别对待?我很困惑。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

您正在观察的问题实际上与可变或不可变类型没有任何关系,这是一个范围界定问题。

考虑以下内容:

a = 0
a += 1

这是有效的,尽管0是不可变的。

另外,这个:

array = [0, 0, 0]
def test_mutable():
    array += [1]

test_mutable()
print(array)

会给你同样的UnboundLocalError

问题在于范围界定。当您尝试在函数内部重用a时,解释器会混淆您所指的a的含义,因为它首先意识到无论您要计算什么,您都希望将其与名称a,因此它为您保留了本地名称a,覆盖了全局a,但是当您尝试将其用于+= 1位时,它会意识到本地a没有任何绑定。

使用array,特别是array[0]时,情况有所不同,因为您不是保留名称array供本地使用,而是继续使用全局{{1} }。

答案 1 :(得分:1)

在像您这样的函数中更新全局变量时,应将其明确声明为全局变量,这将很好地工作。

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)

由于数组将在本地引用中更新,因此输出为[1, 2, 3]。但是,如果您尝试这样做:

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

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