为什么分配给 __class__ 单元格会破坏 `super`?
Why does assigning to the __class__ cell break `super`?
我已阅读 Why is Python 3.x's super() magic? 并了解在方法中使用 super
或 __class__
会自动为该方法创建一个 __class__
单元格变量:
class Demo:
def meth(self):
super().meth()
>>> Demo.meth.__closure__
(<cell at 0x7f4572056138: type object at 0x564bda0e5dd8>,)
>>> Demo.meth.__closure__[0].cell_contents
<class '__main__.Demo'>
而且据我所知,单元格是用来保存闭包变量的,可以自由修改:
def outer():
x = 3
def inner():
print(x)
x = 5
return inner
inner = outer()
inner() # output: 5
>>> inner.__closure__
(<cell at 0x7f2183a5e138: int object at 0x7f2184600460>,)
但是尝试重新分配 __class__
单元格的值会使 super
抛出一个奇怪的错误:
class Demo:
def meth(self):
__class__ = Demo
super().meth()
Demo().meth()
Traceback (most recent call last):
File "untitled.py", line 8, in <module>
Demo().meth()
File "untitled.py", line 6, in meth
super().meth()
RuntimeError: super(): __class__ cell not found
为什么会这样?为什么 __class__
不能像其他闭包变量一样被重新赋值?
你需要一个 nonlocal
语句来赋值给闭包变量,包括神奇的 __class__
闭包变量。在没有 nonlocal
语句的情况下分配给 __class__
会创建一个隐藏魔术闭包变量的局部变量。
您期望 __class__
的行为就好像它是 meth
的本地一样,但实际上它的行为就像是一个不可见的伪范围的本地行为,其中 [=18] 的所有方法=] 是嵌套的。如果它被视为 meth
的本地,则不需要 nonlocal
.
如果你确实添加了一个nonlocal
语句,执行actually will allow you重新分配魔法闭包变量:
class Foo:
def meth(self):
nonlocal __class__
__class__ = 3
super()
Foo().meth()
结果:
Traceback (most recent call last):
File "./prog.py", line 7, in <module>
File "./prog.py", line 5, in meth
RuntimeError: super(): __class__ is not a type (int)
我已阅读 Why is Python 3.x's super() magic? 并了解在方法中使用 super
或 __class__
会自动为该方法创建一个 __class__
单元格变量:
class Demo:
def meth(self):
super().meth()
>>> Demo.meth.__closure__
(<cell at 0x7f4572056138: type object at 0x564bda0e5dd8>,)
>>> Demo.meth.__closure__[0].cell_contents
<class '__main__.Demo'>
而且据我所知,单元格是用来保存闭包变量的,可以自由修改:
def outer():
x = 3
def inner():
print(x)
x = 5
return inner
inner = outer()
inner() # output: 5
>>> inner.__closure__
(<cell at 0x7f2183a5e138: int object at 0x7f2184600460>,)
但是尝试重新分配 __class__
单元格的值会使 super
抛出一个奇怪的错误:
class Demo:
def meth(self):
__class__ = Demo
super().meth()
Demo().meth()
Traceback (most recent call last):
File "untitled.py", line 8, in <module>
Demo().meth()
File "untitled.py", line 6, in meth
super().meth()
RuntimeError: super(): __class__ cell not found
为什么会这样?为什么 __class__
不能像其他闭包变量一样被重新赋值?
你需要一个 nonlocal
语句来赋值给闭包变量,包括神奇的 __class__
闭包变量。在没有 nonlocal
语句的情况下分配给 __class__
会创建一个隐藏魔术闭包变量的局部变量。
您期望 __class__
的行为就好像它是 meth
的本地一样,但实际上它的行为就像是一个不可见的伪范围的本地行为,其中 [=18] 的所有方法=] 是嵌套的。如果它被视为 meth
的本地,则不需要 nonlocal
.
如果你确实添加了一个nonlocal
语句,执行actually will allow you重新分配魔法闭包变量:
class Foo:
def meth(self):
nonlocal __class__
__class__ = 3
super()
Foo().meth()
结果:
Traceback (most recent call last):
File "./prog.py", line 7, in <module>
File "./prog.py", line 5, in meth
RuntimeError: super(): __class__ is not a type (int)