# 作用域、名字空间、属性空间
# 作用域
我们称一个名字能影响的区域为名字的作用域
在Python中,作用域是静态的,也叫词法作用域-即使由名字引入的位置决定的,而不是运行时动态决定的
Python在编译时,根据语法规则将代码划分为不同的代码块,每个代码块形成一个作用域。
- 整个.py文件形成全局作用域,也叫模块作用域
- 遇到函数定义,函数体称为当前作用域的子作用域,并且函数作用域对子作用域是可见的
- 遇到类定义,类定义体称为当前作用域的子作用域,但是类作用域对于子作用域是不可见的
- 在当前作用域和全局作用域之间的部分统称为闭包作用域,一般是闭包函数才会出现这种情况
g = 1 def fun(): fv = 2 def outer(): out = 3 def inner(): inn = 4 return inner class C: c = 1 def __init__(self) -> None: pass def cfun(self): print(g) # OK print(c) # WRONG def fun2(): f2 = 5 class CC: def __init__(self) -> None: pass def ccfun(self): print(f2) # OK
# 命名空间LEGB
命名空间负责存储名字和对象的绑定关系,由于名字绑定关系是有 名字 和 对象 组成的键值对,因而 dict 对象是理想的存储容器。
(G)每个模块背后都有一个dict对象(
__dict__)表示全局名字空间,用于存储全局作用域的绑定关系注意Python中全局名字空间以模块为单位进行划分,而非全局统一
模块的属性空间和全局名字空间实质是同一个对象 -
__dict__属性空间表示对象可以访问到的属性
(L)局部名字空间用于存储作用域内的绑定关系
(E)在作用域存在嵌套的情况下, Python 将内层代码块中依赖的所有外层名字存储在一个容器内,即 闭包名字空间 ( Enclosings )
(B)Python中还存在一个内键名字空间,其中提供了许多内键函数(例如print)或类型(例如int)
在Python调用函数时,需要的上下文实际上就由这四个命名空间组成,查找顺序依次为LEGB

# 属性空间
Python中称对象可以访问到的属性集合为属性空间-
__dict__属性- 对类和包可以直接访问,对函数而言其是空的
← Python程序执行过程 广义赋值语句 →