我想知道 Python 3 中新的 super 是如何实现的。
这个问题是在我做了一个小例子之后出现在我脑海中的,我得到了一个奇怪的错误。 我正在使用 Pyutilib Component architecture (PCA)我已经制作了自定义元类来驱动另一个类的创建:
from pyutilib.component.core import implements, SingletonPlugin, PluginMeta, Interface
class IPass(Interface):
pass
class __MetaPlugin(PluginMeta):
def __new__(cls, name, baseClasses, classdict):
print(cls, name, baseClasses, classdict)
if baseClasses:
baseClasses += (SingletonPlugin,)
return PluginMeta.__new__(cls, name, baseClasses, classdict)
class Pass(metaclass=__MetaPlugin):
implements(IPass)
def __init__(self, inputs=[], outputs=[]):
self.inputs = []
self.outputs = []
class A(Pass):
def __init__(self):
print(self.__class__) # <class '__main__.A'>
print(self.__class__.__class__) # <class '__main__.__MetaPlugin'>
print(PluginMeta.__class__) # <class 'type'>
super().__init__() # SystemError: super(): empty __class__ cell
#Pass.__init__(self) - this works
a = A()
我收到以下错误:
super().__init__() SystemError: super(): empty __class__ cell
我想知道 super() 究竟做了什么,它在 super().__init__()
上引发错误,而所有 self.__class__
,self.__class__.__class__
和 PluginMeta.__class__
存在。额外的“旧方法”- Pass.__init__(self)
正在运行。
最佳答案
TL;DR:当元类尝试调用已定义类中的方法(或实例化它)之前,将发生此 "empty __class__ cell"
错误完成了它的 __new__
和 __init__
,被调用的方法使用 super
。如果在类主体外部定义的函数中编写对 super()
的调用,并尝试将此方法添加到现有类并使用它,也会发生该错误。 (更新:此行为已在 Python 3.6 中修复)
Python 3 super 隐式引用了一个“神奇的”__class__
[*] 名称,它在每个类方法的命名空间中充当单元格变量。
这个变量是在类创建机制的末尾自动创建的——也就是说,只要在 Python 中有类主体,元类的 __new__
和 __init__
正在运行 - 当 __init__
完成时,__class__
单元格被填充并可供类的方法使用。
这是怎么回事,很可能(我没有查看所有代码)在 PluginMeta
初始化代码中,类的 __init__
被调用,在元类结束 __init__
- 因为这个元类的要点之一是处理单例 - 可能发生的是元类机制正在实例化单个实例并填充 __instance__
在从元类的 __init__
返回之前。 super 使用的隐式 __class__
此时不存在。
因此,通过硬编码名称引用父类(super class),就像在 Python2 中的 super
之前必须做的那样 - 并且是实现您想要的目标的最佳方式。
*
- 这不是实例的 self.__class__
属性,它是方法内部实际可用的 __class__
变量:
class A:
def a(self):
print ("Instance's class: {}, "
"actual class where this line is coded: {}".format(
self.__class__, __class__))
class B(A):
pass
运行这个我们有:
>>> B().a()
Instance's class: <class '__main__.B'>, actual class where this line is coded: <class '__main__.A'>
>>>
来自 Python 数据模型:
__class__
is an implicit closure reference created by the compiler if any methods in a class body refer to either__class__
orsuper
. This allows the zero argument form ofsuper()
to correctly identify the class being defined based on lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method.
更多详情请查看PEP 3135
关于python - Python 3 中的 super() 是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13126727/