为什么分配给__class__单元格中断“ super”?

时间:2018-09-20 16:52:30

标签: python closures 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__

1 个答案:

答案 0 :(得分:2)

您需要一个nonlocal语句来分配给闭合变量,包括神奇的__class__闭合变量。在没有__class__语句的情况下分配给nonlocal会创建一个局部变量,该局部变量将隐藏魔术闭合变量。

您期望__class__的行为就像是meth的本地行为,但实际上它的行为好像是它是Demo的所有方法的不可见伪范围的本地行为嵌套。如果将其视为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)
相关问题