Scope(2)

Updated: 2019-01-06

坑!

def run():
    flag = False
    def print_flag():
        print(flag)
    def set_to_true():
        flag = True
    print(flag)
    set_to_true()
    print(flag)
    return flag

run()

结果是

$ python3 test.py
False
False

进阶

在读一个变量时,如果 Python 在当前的 scope 不能找到则尝试在上一层中寻找,如果直到 built-in(也就是系统自带的函数和变量)也无法找到,就返回NameError。所以print_flag()中没有 flag,它向上找到了run()函数里的 flag 并打印出来。

def print_flag():
    print(flag)

而赋值时则不同,如果当前 scope 不存在该变量,Python 会新建一个变量,所以在set_to_true()中新建了一个 flag,它只存在于这个函数中,并没有改变上一层 flag 的值

def set_to_true():
    flag = True

一个解决方法是在 Python3 中使用nonlocal关键字,告诉它这个变量并不是本地的,而应该在上一层寻找。

def set_to_true():
    nonlocal flag
    flag = True

这样再运行程序的结果就对了

$ python3 test.py
False
True

不过 nonlocal 并不被推荐使用。