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