我正在运行Python 2.5,因此此问题可能不适用于Python3。当您使用多重继承创建菱形类层次结构并创建最派生类的对象时,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()
该代码做直观的事情,它打印:
D init
B init
C init
A init
但是,如果注释掉B的init函数中对super的调用,则不会调用A或C的init函数。这意味着B对super的调用以某种方式知道C在整个类层次结构中的存在。我知道super返回带有重载get运算符的代理对象,但是D的init定义中的super返回的对象如何将C的存在传达给B的init定义中的super返回的对象?超级调用的后续调用所使用的信息是否存储在对象本身上?如果是这样,为什么不是super而是self.super?
编辑:Jekke非常正确地指出它不是self.super,因为super是类的属性,而不是类的实例。从概念上讲,这是有道理的,但实际上,super也不是该类的属性!您可以通过在解释器中进行测试,方法是创建两个类A和B,其中B继承自A,然后调用dir(B)
。它没有super
或__super__
属性。
我在下面提供了许多链接,这些链接比我所希望的更详细,更准确地回答了您的问题。但是,我也会用我自己的话回答您的问题,以节省您的时间。我会以分数为准-
__mro__
属性,该属性存储该特定实例的方法解析顺序。__init__
在指定为第一个参数的类(在本例中为DC之后的类)之后,super在MRO的类中寻找与(在您的情况下)匹配的方法。 找到匹配方法后(例如在 BC1 类中),将调用该方法。
(此方法应该使用super,所以我假设它确实使用了-请参见Python的super很漂亮,但不能使用-
下面的链接)然后,该方法将在对象类的MRO中搜索下一个方法,即 BC1 。
重复漂洗直到找到并调用所有方法。
您的示例的说明
MRO: D,B,C,A,object
super(D, self).__init__()
叫做。isinstance(self,D)=>是 B.__init__
找到并打电话
B.__init__
来电 super(B, self).__init__()
。isinstance(self,B)=>假
isinstance(self,D)=>真
因此,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/
超级的文档:
http
://docs.python.org/library/functions.html本页
底部有一个关于超级的不错的部分:
http:/ /docstore.mik.ua/orelly/other/python/0596001886_pythonian-
chp-5-sect-2.html
我希望这有助于清除它。
在python中,键为null时是否可以进行右连接。也就是说,我是否可以连接日期框以仅从右侧生成与左侧不匹配的值?
问题内容: 之间有什么区别: 我看到super在只有单一继承的类中经常使用它。我知道为什么你会在多重继承中使用它,但是不清楚在这种情况下使用它的好处。 问题答案: 单继承的好处是微不足道的-大多数情况下,你不必将基类的名称硬编码到每个使用其父方法的方法中。 但是,如果不使用,几乎不可能使用多重继承。这包括常见的惯用语,例如,接口,抽象类等。这扩展到了以后扩展你的代码的代码。如果以后有人想编写一个扩
我刚刚开始使用覆盖率。于是决定做一个简单的测试来检查它是如何工作的。 Sample.py 测验派克 如您所见,我所有的代码都覆盖了测试,py.test说它们都通过了。我希望Coverage.py显示100%的覆盖率。嗯,不。 然后我添加了这段代码: 并删除了所有测试功能。在那之后,是保险范围。py显示100%: 为什么会这样?我们不应该买保险。py显示代码测试覆盖率,而不仅仅是执行覆盖率?我读过官
问题内容: 我在使用Python进行面向对象的编程方面非常陌生,并且在理解函数(新样式类)时遇到困难,特别是在涉及多重继承时。 例如,如果你有类似的东西: 我不明白的是:该类会继承两个构造函数方法吗?如果是,那么哪个将与一起运行,为什么? 而如果要运行另一个呢?我知道这与Python方法解析顺序有关。 问题答案: Guido自己在他的博客文章(包括两次较早的尝试)中对此进行了合理的详细说明。 在你
前面不止一次讲过, Python 中子类会继承父类所有的类属性和类方法。严格来说,类的构造方法其实就是实例方法,因此毫无疑问,父类的构造方法,子类同样会继承。 但我们知道,Python 是一门支持多继承的面向对象编程语言,如果子类继承的多个父类中包含同名的类实例方法,则子类对象在调用该方法时,会优先选择排在最前面的父类中的实例方法。显然,构造方法也是如此。 举个例子: 运行结果,结果为: 我是人,
问题内容: 当你只想执行但不处理异常时,如何在Python中进行呢? 以下是正确的方法吗? 问题答案: 要么 所不同的是,第一个也将赶上KeyboardInterrupt,SystemExit和类似的东西,这是直接来源于,没有