Question

I have a inherited a class and overwritten a method who also is inherited from a base class. But the thing is that the middle method creates an exception that i would like to bypass by calling the first declared method. Is there a way to specify to the mro that ignores the second calls?

An example could be:

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

Thanks a lot

PD: Something like class BaseB(Base, BaseA) could work?

Was it helpful?

Solution

Normally you'd fix that method instead.

However, the first argument to super() is the place to start searching for the next method from. Normally that'd be the current class, but you can also pass in the base class:

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

Here, super() takes the MRO of type(self), finds BaseA in that MRO, and looks for the next class implementing __init__.

Another way to bypass the problematic __init__ method is to just call the unbound method on Base directly:

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

bypassing any MRO searches entirely.

OTHER TIPS

The Right Way to fix this is to create a new class hierarchy which overrides the offending method with an improved implementation. If you insist on hackery though, this may be what you want:

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

Note that I'm asking for the super implementation with respect to BaseA, which means that the BaseA implementation is never used.


However, this can do the Wrong Thing when diamond inheritance is involved. Consider:

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()

The output is :

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

BaseC was skipped even though that's not what we wanted. This is because BaseC came between BaseB and BaseA in the method resolution order, so when we skipped from BaseB to BaseA we inadvertently neglected BaseC.

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

How bout just

Base.__init__(self)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top