Python静态作用域名字搜索规则

详细见<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>}
'''

猜你喜欢

转载自blog.csdn.net/lijil168/article/details/82015009