详细见<Python进阶_关于命名空间与作用域(详解)>https://www.jb51.net/article/114951.htm
在程序中引用了一个名字,Python是怎样搜索到这个名字呢?
在程序运行时,至少存在三个命名空间可以被直接访问的作用域:
Local
首先搜索,包含局部名字的最内层(innermost)作用域,如函数/方法/类的内部局部作用域;
Enclosing
根据嵌套层次从内到外搜索,包含非局部(nonlocal)非全局(nonglobal)名字的任意封闭函数的作用域。如两个嵌套的函数,内层函数的作用域是局部作用域,外层函数作用域就是内层函数的 Enclosing作用域;
Global
倒数第二次被搜索,包含当前模块全局名字的作用域;
Built-in
最后被搜索,包含内建名字的最外层作用域。
程序运行时,LGB三个作用域是一定存在的,E作用域不一定存在;
经典官方示例:
def scope_test():
def do_local():
spam = 'local spam'
def do_nonlocal():
nonlocal spam # 当外层作用域不存在spam名字时,nonlocal不能像global那样自作主张定义一个
spam = 'nonlocal spam' # 自由名字spam经nonlocal声明后,可以做重绑定操作了,可写的。
def do_global():
global spam # 即使全局作用域中没有名字spam的定义,这个语句也能在全局作用域定义名字spam
spam = 'global spam' # 自有变量spam经global声明后,可以做重绑定操作了,可写的。
spam = 'test spam'
do_local()
print("After local assignment:", spam) # After local assignment: test spam
do_nonlocal()
print("After nonlocal assignment:", spam) # After nonlocal assignment: nonlocal spam
do_global()
print("After global assignment:", spam) # After global assignment: nonlocal spam
scope_test()
print("In global scope:", spam) # In global scope: global spam
试一试:
# coding=utf-8
def test1():
print(i)
'''test1()
NameError: name 'i' is not defined
print()从LGB空间都没找到自由变量i!!!
'''
def test2():
print(i)
i=2
'''test2()
UnboundLocalError: local variable 'i' referenced before assignment
test2()定义了局部变量i,但是print()在i赋值前被引用!!!
'''
def test3():
print(i)
i=2
test3()
'''
2
'''
def test4():
i=1
print(i)
i=2
test4()
print(i)
'''
1
2
'''
def test5():
global i
i=1
print(i)
i=2
test5()
print(i)
'''
1
1
'''
def test6():
global i
i=3
print(i)
test6()
print(i)
'''
3
3
'''
'''def test7():
nonlocal i #绑定到外部的i
i=3
print(i)
i=1
test7()
print(i)
SyntaxError: no binding for nonlocal 'i' found
'''
def test8():
i=9
def temp():
nonlocal i #绑定到外部的i
i=10
print(i)
temp()
print(i)
test8()
'''
9
10
'''
print(test8.__globals__)
'''
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001D5C2E8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\li\\workspace\\temp\\e\\ttt\\try6.py', '__cached__': None, 'test1': <function test1 at 0x00000000004D4E18>, 'test2': <function test2 at 0x00000000027AF268>, 'test3': <function test3 at 0x0000000002930840>, 'i': 3, 'test4': <function test4 at 0x00000000029308C8>, 'test5': <function test5 at 0x0000000002930950>, 'test6': <function test6 at 0x00000000029309D8>, 'test8': <function test8 at 0x0000000002930A60>}
'''