2014-02-25 31 views
0

我有一个继承的类并覆盖了一个方法,它也从基类继承。但事情是,中间方法创建一个异常,我想通过调用第一个声明的方法绕过。有没有办法指定mro忽略第二个电话?Python超级绕过MRO

一个例子可以是:

class Base(object): 
    def __init__(self): 
     res = "Want this" 
     print res 

class BaseA(Base): 
     def __init__(self): 
      res = super(BaseA, self).__init__() 
      res = "Not this" 
      print res 

class BaseB(BaseA): 
     def __init__(self): 
      res = super(BaseB, self).__init() 
      #At this poing res is "Not this" 
      #The desire is that it would be "Want this" 
      print res 

非常感谢

PD: 喜欢的东西类BaseB(基地BaseA)可以工作?

+0

“类BaseB(Base,BaseA)可以工作吗?”。不,它会引发异常:调用元类时出现TypeError:错误 无法为基Base,BaseA'创建一致的方法解析 order(MRO)。在这种情况下,你必须直接调用特定的父类... – Bakuriu

回答

3

通常情况下您会修改该方法。

但是,super()的第一个参数是从开始搜索下一个方法的地方。通常情况下这会是当前的类,但你也可以通过在基类:

class BaseB(BaseA): 
    def __init__(self): 
     res = super(BaseA, self).__init__() 

这里,super()需要的type(self)的MRO,在MRO发现BaseA,并寻找下一个类实现__init__

另一种方法绕过问题__init__方法是只需调用未结合的方法上Base直接:

class BaseB(BaseA): 
    def __init__(self): 
     res = Base.__init__(self) 

绕过任何MRO完全搜索。

+0

非常感谢。它绕过超级并直接调用基类__init__。一个简单有效的解决方案,太棒了。为了好奇心,我分支并测试第一个修复程序,看看发生了什么。 – cllamach

0

如何回合刚刚

Base.__init__(self)

1

使用正确的方法解决这个问题是创建一个新的类层次结构,其覆盖与改进执行违规方法。如果你坚持两轮牛车虽然,这可能是你想要什么:

class BaseB(BaseA): 
     def __init__(self): 
      res = super(BaseA, self).__init() 
      #At this poing res is "Not this" 
      #The desire is that it would be "Want this" 
      print res 

请注意,我所要求的超级实现相对于BaseA,这意味着BaseA实现从未使用过。


然而,这可以做的时候菱形继承涉及错误的事情。试想一下:

class Base(object): 
    def __init__(self): 
     print 'initing Base' 

class BaseA(Base): 
    def __init__(self): 
     print 'initing BaseA' 
     res = super(BaseA, self).__init__() 

class BaseB(BaseA): 
    def __init__(self): 
     print 'initing BaseB' 
     res = super(BaseA, self).__init__() 

class BaseC(BaseA): 
    def __init__(self): 
     print 'initing BaseC' 
     res = super(BaseC, self).__init__() 

class BaseD(BaseB, BaseC): 
    def __init__(self): 
     print 'initing BaseD' 
     res = super(BaseD, self).__init__() 

print BaseD() 

输出是:

initing BaseD 
initing BaseB 
initing Base 
<__main__.BaseD object at 0x7f1e693a0110> 

BaseC被跳过,即使这不是我们想要的。这是因为BaseC在方法解析顺序中出现在BaseBBaseA之间,所以当我们从BaseB跳到BaseA时,我们无意中忽略了BaseC

>>> print [cls.__name__ for cls in BaseD.mro()] 
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object'] 
+0

'super(BaseA,self)'仍然使用'type(self)'的MRO,不需要在这里自己进行计算。 –

+0

如果'self'的类型是'class BaseD(BaseA,BaseB)',那么上面的代码会产生一个无限循环,否?我只是想说明,在钻石继承的情况下这不是那么容易。 – bukzor

+0

蟒蛇防御;你不能创建'class BaseD':'TypeError:错误时调用元类基地\ n不能创建一个一致的方法解析\诺德(MRO)BaseB BaseA' –