Я читал Почему Python 3.x супер() магия? и понять, что использование 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__
. Присвоение __class__
без nonlocal
оператора создает локальную переменную, которая скрывает магическую замыкающую переменную.
Вы ожидаете, что __class__
будет вести себя так, как если бы он был локальным для meth
, но он фактически ведет себя так, как будто он локален для невидимого псевдообмена, в котором все методы Demo
вложены. Если бы он рассматривался как локальный для meth
, вам не требовалось бы nonlocal
.
Если вы добавите nonlocal
оператор, реализация на самом деле позволит вам переназначить переменную закрытия заклинания:
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)
__class__
означает, что__class__
является локальной переменной вместо закрывающей переменной». Dupe?