1

我有一个继承的类并覆盖了一个也继承自基类的方法。但问题是中间方法创建了一个异常,我想通过调用第一个声明的方法来绕过它。有没有办法指定忽略第二次呼叫的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(Base, BaseA) 类的东西可以工作吗?

4

3 回答 3

6

通常,您会改用该方法。

但是,第一个参数super()是从 开始搜索下一个方法位置。通常这是当前类,但您也可以传入基类:

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

在这里,super()获取 的 MRO type(self),在该 MRO 中找到BaseA,并寻找下一个实现 的类__init__

绕过有问题的方法的另一种__init__方法是直接调用未绑定的方法Base

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

完全绕过任何 MRO 搜索。

于 2014-02-25T19:26:21.887 回答
2

解决这个问题的正确方法是创建一个新的类层次结构,它通过改进的实现覆盖有问题的方法。但是,如果您坚持使用hackery,那么这可能就是您想要的:

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所以当我们从 跳到 时BaseBBaseA我们不经意间忽略了BaseC.

>>> print [cls.__name__ for cls in BaseD.mro()]
['BaseD', 'BaseB', 'BaseC', 'BaseA', 'Base', 'object']
于 2014-02-25T19:29:57.547 回答
0

刚刚怎么样

Base.__init__(self)

于 2014-02-25T19:29:44.637 回答