Jos*_*vin 51 python constructor multiple-inheritance super python-2.5
我正在运行Python 2.5,因此这个问题可能不适用于Python 3.当您使用多重继承创建钻石类层次结构并创建派生最多类的对象时,Python会执行Right Thing(TM).它调用派生最多类的构造函数,然后调用从左到右列出的父类,然后是祖父母.我熟悉Python的MRO ; 那不是我的问题.我很好奇从super返回的对象实际上如何管理与父类中的super调用正确的顺序进行通信.考虑这个示例代码:
#!/usr/bin/python
class A(object):
def __init__(self): print "A init"
class B(A):
def __init__(self):
print "B init"
super(B, self).__init__()
class C(A):
def __init__(self):
print "C init"
super(C, self).__init__()
class D(B, C):
def __init__(self):
print "D init"
super(D, self).__init__()
x = D()
Run Code Online (Sandbox Code Playgroud)
代码做直观的事情,它打印:
D init
B init
C init
A init
Run Code Online (Sandbox Code Playgroud)
但是,如果你在B的init函数中注释掉对super的调用,则不会调用A和C的init函数.这意味着B对super的调用在某种程度上意识到C在整个类层次结构中的存在.我知道super返回一个带有重载get运算符的代理对象,但是在D的init定义中super返回的对象如何将C的存在传达给B的init定义中super返回的对象?后续超级使用调用的信息是否存储在对象本身上?如果是这样,为什么不是超级而不是self.super?
编辑:Jekke非常正确地指出它不是self.super,因为super是类的属性,而不是类的实例.从概念上讲,这是有道理的,但在实践中,超级也不是班级的属性!您可以在解释器中通过创建两个类A和B来测试它,其中B继承自A,并且调用dir(B)
.它没有super
或__super__
属性.
Jac*_*son 34
更改您的代码这一点,我认为它会解释的东西(可能是super
在看哪里,也就是说,B
是在__mro__
?):
class A(object):
def __init__(self):
print "A init"
print self.__class__.__mro__
class B(A):
def __init__(self):
print "B init"
print self.__class__.__mro__
super(B, self).__init__()
class C(A):
def __init__(self):
print "C init"
print self.__class__.__mro__
super(C, self).__init__()
class D(B, C):
def __init__(self):
print "D init"
print self.__class__.__mro__
super(D, self).__init__()
x = D()
Run Code Online (Sandbox Code Playgroud)
如果你运行它,你会看到:
D init
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
B init
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
C init
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
A init
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)
另外值得一看的是Python的Super是漂亮的,但你不能使用它.
bat*_*rat 15
我在下面提供了一系列链接,它们比我希望的更详细,更准确地回答您的问题.不过,我会用自己的话回答你的问题,为你节省一些时间.我会说点 -
__mro__
属性,用于存储该特定实例的方法解析顺序.__init__
在指定为第一个参数的类(在本例中为DC之后的类)之后,super会在MRO的类中查找匹配(在您的情况下)的方法. 您的示例的说明
MRO: D,B,C,A,object
Run Code Online (Sandbox Code Playgroud)
super(D, self).__init__()
叫做.isinstance(self,D)=>真 在D的右侧的类中搜索MRO中的下一个方法.
B.__init__
找到并打电话
B.__init__
电话 super(B, self).__init__()
.
isinstance(self,B)=> False
isinstance(self,D)=> True
因此,MRO是相同的,但搜索继续到B的右边,即C,A,逐个搜索对象.下一个__init__
发现被称为.
等等等等.
超级
http://www.python.org/download/releases/2.2.3/descrintro/#cooperation 的解释
当使用超级
http://fuhm.net/super-harmful/
Pythons MRO算法时需要注意的事项:
http ://www.python.org/download/releases/2.3/mro/
super的文档:
http ://docs.python.org/library/functions.html
这个页面的底部有一个很好的超级部分:
http:/ /docstore.mik.ua/orelly/other/python/0596001886_pythonian-chp-5-sect-2.html
我希望这有助于澄清它.
只是猜测:
self
在所有四种方法中都引用同一个对象,即类D
.所以,在B.__init__()
调用中super(B,self)
知道整个钻石的祖先,self
它必须从'之后'获取方法B
.在这种情况下,它是C
班级.
归档时间: |
|
查看次数: |
27067 次 |
最近记录: |