关于python:混淆变量范围(来自外部范围的阴影变量)

Confusing variable scope (shadowing variable from outer scope)

本问题已经有最佳答案,请猛点这里访问。

我曾经用C、C和Java编程。现在我使用python有一段时间了,但是在理解变量范围时遇到了一些问题,这对我来说现在很混乱。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def f1():
    print(spam)   # spam magically come from outer scope. ok...


def f2():
    spam ="bbb"  # assignment shadows variable from outer scope (logical result of f1)
    print(spam)   # printing local spam variable


def f3():
    print(spam)   # ERROR: unresolved reference 'spam'
    spam ="ccc"  # in f1 function everything was fine but adding assignment AFTER
                  # printing (in opposite to f2 function) causes error in line above


def f4():
    print(spam)   # nothing wrong here, assignment line below is commented
    # spam ="ccc"

spam ="aaa"

为什么地球上的函数可以达到超出其范围的变量?为什么从外部范围隐藏变量是可以的,但只有在我们以前没有使用它的情况下才可以?


在执行之前,python代码被编译为字节代码。这意味着python可以分析函数如何使用变量。变量在函数中是全局变量或局部变量,但不能同时是全局变量和局部变量,并且不能更改。

spamf1中是全局的,因为它从未被分配。spamf2中是本地的,因为它是分配的。同样适用于f3。由于spam='ccc'spamf3中是本地的。使用print(spam)语句,您试图在分配局部变量之前访问它。

可以在函数内部使用global spam强制声明变量名为全局变量。

本地保持本地。即使在本地命名空间中删除了变量,python也不会在父范围中查找名称:

1
2
3
4
5
6
7
8
9
spam = 123

def f():
    spam = 42
    print(spam)  # 42
    del spam
    print(spam)  # UnboundLocalError

f()

如果要分配全局变量,则需要声明它:

1
2
3
4
5
6
7
8
9
spam = 123

def f():
    global spam
    spam = 42
    print(spam)  # 42

f()
print(spam)  # 42