super(...).__init__() vs Base.__init__(self)



Are there any best practice guidelines for when to use
super(Class, self).__init__()
vs
Base.__init__(self)
to call a base class __init__()?

The super() method only works correctly in multiple inheritance when the base classes are written to expect it, so "Always use super()" seems like bad advice. OTOH sometimes you need super() to get correct behaviour. ISTM "Only use super() when you know you need it" might be the best advice. Is there any conventional wisdom on this?

The question arises from a naive use of super() in a post on the tutor list. This code gives an AttributeError because Base.__init__() is never called:

import threading

class Base(object):
def __init__(self):
self.x = 1

class Derived(threading.Thread, Base):
def __init__(self):
super(Derived, self).__init__()

d=Derived()
d.x

If the order of base classes is reversed, the reference to d.x works but of course threading.Thread.__init__() is never called.

1. One way to fix the code is to call Base.__init__() and threading.Thread.__init__() explicitly in Derived.__init__().

2. Another fix is for Base.__init__() to call super(Base, self).__init__() and to list Base first in the list of base classes. This is fragile - it depends on the order of base classes and adding another base class would break it.

3. A third fix might be to change both Base and threading.Thread() to call super(...).__init__(). This might break existing code that is written in the style of fix 1 (calling both base class __init__() methods explicitly).

I prefer the first fix, it is explicit and fairly robust - it works if the order of bases is changed, and it's pretty clear from the body of Derived.__init__() that if you add another base class, you should change __init__().

Any other opinions? Any consensus about the "best" way to do this?

BTW I understand what super() does, I know why the original code is broken, I'm not asking for help with that. I'm wondering what others think best practices are.

Thanks,
Kent
.



Relevant Pages

  • Re: multiple inheritance
    ... > def foo: ... That is because a single call to super only calls a single method from one ... check for the existence of the base class method, ... You can also ask a class the order in which its base classes are examine ...
    (comp.lang.python)
  • super() not a panacea?
    ... The super object is considered a solution to the "diamond problem". ... it generally requires that the ultimate base class know that it ... def m: ...
    (comp.lang.python)
  • Re: Accessing mangled class attrbutes
    ... Steve Juranich wrote: ... super(HtmlWriter, self).__write ... There is no method '__write' in the base class, ...
    (comp.lang.python)
  • Re: super() doesnt get superclass
    ... Why are you looking for the superclass of A? ... classis/are the superclass" is an implementation detail that you ... super is sadly confusing and hard to use. ... provided all the base classes *and their bases classes* themselves also ...
    (comp.lang.python)
  • Re: Copying objects and multiple inheritance
    ... some of the instances in the hierarchy ... copies they need some information updated a little differently), so how can I make sure all the information is copied as it is supposed to be even for the base classes that have special requirements. ... All classes must be written with cooperation in mind, using super() the "right" way. ... That said, and since multiple inheritance is the heart of the problem, maybe you can redesign your solution *without* using MI? ...
    (comp.lang.python)