Python多重继承超级函数

时间:2015-10-19 19:11:06

标签: python multiple-inheritance

我对python多重继承感到困惑。

例如,如果你有:

  app.UseFacebookAuthentication(
           appId: ConfigurationManager.AppSettings["FacebookId"],
           appSecret: ConfigurationManager.AppSettings["FacebookSecret"]);

        app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
        {
            ClientId = ConfigurationManager.AppSettings["GoogleId"],
            ClientSecret = ConfigurationManager.AppSettings["GoogleSecret"],
        });

方法解析顺序(MRO)将是D-C-B-A。

为什么订单不是D-C-A-B-A?

4 个答案:

答案 0 :(得分:2)

Python文档:

  

对于新式类,动态排序是必要的,因为所有多重继承的情况都表现出一个或多个菱形关系(其中至少有一个父类可以通过最底层的多个路径访问)。例如,所有新样式类都继承自object,因此任何多重继承的情况都会提供多个到达对象的路径。 为了防止多次访问基类,动态算法将搜索顺序线性化,以保留每个类中指定的从左到右的顺序,只调用每个父类,这是单调的(意味着一个类可以被子类化,而不会影响其父级的优先顺序)。总之,这些属性使得设计具有多重继承的可靠且可扩展的类成为可能。有关更多详细信息,请参阅https://www.python.org/download/releases/2.3/mro/

答案 1 :(得分:1)

您只实例化一个对象。 Python允许每个祖先的__init__在MRO中只执行一次。因此,我们不会同时执行A-> C和A-> B关系A.__init__

如果解释得那么多,你可能会认为我们会得到DCAB ......但由于B还需要A.__init__,因此在确定执行顺序之前,MRO足以耐心解析整个图形。

答案 2 :(得分:1)

粗略地讲,MRO是通过将所有基础从深度优先,从左到右,然后删除任何重复,只留下最后一个来给出的。

算法是这样的,对于任何基类,mro中基类的顺序总是相同的(如果这是不可能的,我相信你会得到一个错误)。

如果没有删除重复项,则订单实际上是D-C-A-object-B-A-object。由于许多原因,这令人困惑。首先,如果方法调用super,就像你的情况一样,那么可以调用相同的方法两次。其次,B的实现期望在方法解析顺序中优先于A和对象是合理的。如果它覆盖A的属性,则预计不会反转此覆盖。

答案 3 :(得分:1)

MRO是D-C-B-A的原因在于它是D-C-A-B-A(或D-C-A-B)会产生奇怪的效果。在此特定示例中,A类构造函数不带参数显式执行仅在钻石继承树中有效的super()调用。如果它没有进行super调用,则B构造函数将无法从A构造函数调用。如果构造函数接受了参数,则A构造函数将被卡在岩石和硬地之间。如果它没有打电话给super那么它就不会在钻石继承中发挥作用。如果它确实调用了super,那么由于object.__init__没有参数,如果它没有在钻石继承模式中使用,构造函数就会失败。