TL; DR :此行为自Python 2.1 PEP 227:Nested
Scopes以来就存在,并且在那时是已知的。如果名称是在类主体中分配的(例如
y),则假定该名称是局部/全局变量;如果未将其分配给(
x),则它也可能指向闭包单元。词汇变量不会显示为类主体的本地/全局名称。
在Python 3.4上,
dis.dis(func)显示以下内容:
>>> dis.dis(func) 40 LOAD_ConST 1 ('xlocal') 3 STORE_DEREF 0 (x) 56 LOAD_ConST 2 ('ylocal') 9 STORE_FAST 0 (y) 6 12 LOAD_BUILD_CLASS 13 LOAD_CLOSURE 0 (x) 16 BUILD_TUPLE 1 19 LOAD_ConST 3 (<pre object C at 0x7f083c9bbf60, file "test.py", line 6>) 22 LOAD_ConST 4 ('C') 25 MAKE_CLOSURE 0 28 LOAD_ConST 4 ('C') 31 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 34 STORE_FAST 1 (C) 37 LOAD_ConST 0 (None) 40 RETURN_VALUE
将
LOAD_BUILD_CLASS负载加载
builtins.__build_class__到堆栈上;这被称为参数
__build_class__(func,name); 这里
func是类的身体,
name是
'C'。类主体是该函数的常量#3
func:
>>> dis.dis(func.__pre__.co_consts[3]) 60 LOAD_NAME 0 (__name__) 3 STORE_NAME 1 (__module__) 6 LOAD_ConST 0 ('func.<locals>.C') 9 STORE_NAME 2 (__qualname__) 7 12 LOAD_NAME 3 (print) 15 LOAD_CLASSDEREF 0 (x) 18 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 21 POP_TOP 8 22 LOAD_NAME 3 (print) 25 LOAD_NAME 4 (y) 28 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 31 POP_TOP 9 32 LOAD_ConST 1 (1) 35 STORE_NAME 4 (y) 38 LOAD_ConST 2 (None) 41 RETURN_VALUE
在类体内,
x通过
LOAD_CLASSDEREF(15)访问,而
y通过
LOAD_NAME(25)加载。的
LOAD_CLASSDEREF是一个Python
3.4+ *** 作码从具体内的类主体闭合细胞(在以前的版本,通用载荷值
LOAD_DEREF被使用); 该
LOAD_NAME是从装载值 当地人 ,然后
全局 。但是,闭包单元既不显示为局部变量,也不显示为全局变量。
现在,由于该名称
y存储在类主体中(35),因此该名称始终用作闭包单元而不是本地/全局名称。闭包单元格不会显示为类主体的局部变量。
自从实现PEP 227嵌套范围以来,这种行为就一直存在。当时BDFL声明不应解决此问题-因此,这已经超过13年了。
自PEP 227以来唯一的变化是
nonlocal在Python 3中的添加;如果在类主体中使用它,则该类主体可以在包含范围内设置单元格的值:
x = "xtop"y = "ytop"def func(): x = "xlocal" y = "ylocal" class C: nonlocal y # y here now refers to the outer variable print(x) print(y) y = 1 print(y) print(C.y)func()
现在的输出是
xlocalylocal1Traceback (most recent call last): File "test.py", line 15, in <module> func() File "test.py", line 13, in func print(C.y)AttributeError: type object 'C' has no attribute 'y'
也就是说,
print(y)读取
y包含作用域的单元格
y = 1的值,然后在该单元格中设置该值;在这种情况下,不会为class创建任何属性
C。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)