Python类作用域规则

Python类作用域规则,第1张

Python类作用域规则

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



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5631159.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存