19.名称空间和作用域

1.名称空间

  • 内置名称空间

    如内置函数名print

    存放一些内置名字,随python解释器启动而产生,关闭而回收

  • 全局名称空间

    y运行顶级代码产生的,只要不是函数内定义的,也不是内置的就是全局名称空间

    文件开始执行而产生,执行完毕而回收

    import sys #模块名sys
    
    x=1 #变量名x
    
    if x == 1:
        y=2 #变量名y
    
    def foo(x): #函数名foo
        y=1
        def bar():
            pass
    
    Class Bar: #类名Bar
        pass
    
  • 局部名称空间

    函数的形参、函数内定义的名字

    伴随函数的调用而临时产生,调用结束而回收

    def foo(x):
        y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中
    

2.作用域与优先级

  • 全局作用域:内置名称空间+全局名称空间
  • 局部作用域:局部名称空间
  • 优先级
1.加载顺序
内置名称空间>全局名称空间>局部名称空间
2.销毁顺序
局部名称空间>全局名称空间>内置名称空间
3.名字的查找优先级:当前所在的位置向上一层一层查找
#内置名称空间
#全局名称空间
#局部名称空间

#例:如果当前在全局名称空间:
#全局名称空间-->内置名称空间

例1:起始位置是局部作用域,所以先查找局部空间

x=100 #全局作用域的名字x
def foo():
    x=300 #局部作用域的名字x
    print(x) #在局部找x
foo()#结果为300

例2:起始位置是全局,先在全局名称空间查找

x=100
def foo():
    x=300 #在函数调用时产生局部作用域的名字x
foo()
print(x) #在全局找x,结果为100

例3:名称空间的嵌套关系是以函数定义阶段为准,与调用位置无关

def func():
    print(x)

x=111
func()
  • 总结
名称空间的嵌套关系决定名字的查找顺序
而名称空间的嵌套关系是以函数定义阶段为准的
即函数的嵌套关系与名字的查找顺序是在定义阶段就已经确定好的

3.作用域的作用范围

  • 全局作用域
全局作用域:内置名称空间、全局名称空间
1.全局存活
2.全局有效:被所有函数共享
  • 局部作用域:局部名称空间
1.临时存活
2.局部有效:函数内有效
  • LEGB
#built-in
#global
def f1():
	#enclosing
	def f2():
		#enclosing
		def f3():
			#local
			pass

4.global与nonlocal

  • global
#如果要在局部想要修改全局的名字对应的值(不可变类型),需要用global
x=111
def func():
    global x #声明x这个名字是全局的名字,不要再造新的名字了
    x=222
func()
print(x)
  • nonlocal
#修改函数外层函数包含的名字对应的值(不可变类型),若一直到最外层函数都找不到修改值,则会报错
def  f1():
    x=2
    def f2():
        nonlocal x
        x=3
    f2() #调用f2(),修改f1作用域中名字x的值
    print(x) #在f1作用域查看x

f1()

#结果
3
原文地址:https://www.cnblogs.com/Psc-mmf/p/13937516.html