Builtn super() function. How to use it with multiple inheritance? And why should I use it at all?

Jean-Michel Pichavant jeanmichel at sequans.com
Thu Jul 29 06:08:54 EDT 2010


Steven D'Aprano wrote:
> On Sun, 25 Jul 2010 13:58:00 +1200, Gregory Ewing wrote:
>
>   
>> Lacrima wrote:
>>
>>     
>>> But what if SuperClass1 is from third party library?
>>>       
>> If it hasn't been designed for super(), then you can't use super() with
>> it.
>>
>> super() only works when *every* class in the hierarchy has been designed
>> with it in mind.
>>     
>
>
> That incorrect. You can certainly use super() with classic classes in the 
> hierarchy, and super() didn't even exist when they were created.
>
>
>   
>>>> class Parent:
>>>>         
> ...     def method(self, arg):
> ...             return repr(arg)
> ...
>   
>>>> class Classic(Parent):
>>>>         
> ...     def method(self, arg):
> ...             return "argument was %s" % Parent.method(self, arg)
> ...
>   
>>>> class New(object, Classic):
>>>>         
> ...     def method(self, arg):
> ...             return super(New, self).method(arg).upper()
> ...
>   
>>>> x = New()
>>>> x.method('spam')
>>>>         
> "ARGUMENT WAS 'SPAM'"
>
>
> The problem isn't super(), and people who give glib advise "don't use 
> super()" are just compounding the problem. The problem is with multiple 
> inheritance where methods have different method signatures. If you don't 
> change the method signatures, super() will work fine.
>
> Advising people not to use super() might make people feel virtuous, but 
> it doesn't do anything to help the reader write non-buggy MI hierarchies. 
> It pushes the effort of dealing with multiple inheritance onto them, 
> forcing them to re-implement the MRO, probably badly. Can you re-
> implement the C3 algorithm? Have you even heard of it? If you answer No 
> to either of those questions, chances are high that trying to deal with 
> the MRO manually will lead to worse bugs than using super().
>
> Should you use super()?
>
> 1. If you're doing multiple inheritance with metaclasses, you MUST use 
> super().
>
> 2. If you're using single inheritance only, and never modify method 
> signatures, there is no reason not to use super().
>
> 3. If you're using mixins, you should use super().
>
> 4. If you never modify method signatures, then you should use super().
>
> 5. If you do modify method signatures, you shouldn't do that (except 
> possibly in constructors, and even there only cautiously). But if you do 
> it anyway, then you should use super() *except* in the methods where you 
> modify the signature.
>
> 6. If you don't use super(), chances are that your class hierarchy is 
> still buggy, but instead of failing loudly and noisily with an exception, 
> it's silently giving the wrong results.
>
> 7. If you can avoid multiple inheritance in favour of another technique 
> (such as composition), you should strongly consider that.
>
>
>
>   
I think you're missing the point that super for most of us is a 
dangerous guess game. It makes implicit what would *really* need to be 
explicit.

class Base1(object):
    def foo(self):
       print 'Base1'


class Base2(object):
    def foo(self):
       print 'Base1'


class Sub(Base1, Base2):
    def foo(self):
           # which  base version to call ???
           # choice A
                 # use super an pray that it will do what I need (better 
know exactly how the MRO works)
                 # also pray that further readers know as much as I do  
about super
           # choice B
                 # use explicit calls so I can choose which algorithm I 
want to use, calling Base1, Base2 or both of them
                 # If the choice is too difficult, that means one thing 
=> my inheritance design is crap => rewrite it properly.

Super is known for being required for diamond inheritance, and this 
reputation is well earned. Outside this scope, super's not required.

JM
        



More information about the Python-list mailing list