invoking a method from two superclasses

Scott David Daniels Scott.Daniels at Acm.Org
Tue Jun 30 23:57:27 EDT 2009


Mitchell L Model wrote:
>> From: Scott David Daniels <Scott.Daniels at Acm.Org>
>> Date: Tue, 30 Jun 2009 16:49:18 -0700
>> Message-ID: <ieudnfm_J89EP9fXnZ2dnUVZ_g6dnZ2d at pdx.net>
>> Subject: Re: invoking a method from two superclasses
>>
>> Mitchell L Model wrote:
>>> In Python 3, how should super() be used to invoke a method defined in C
>>> that overrides its two superclasses A and B, in particular __init__?
>>> ...
>>> I've discovered the surprising fact described in the documentation of super
>>> <http://docs.python.org/3.1/library/functions.html#super>
>>> that specifying a class as the first argument of super means to skip that class when
>>> scanning the mro so that ....
>>>
>>> This seems weird. Would someone please give a clear example and explanation of
>>> the recommended way of initializing both superclasses in a simple multiple inheritance
>>> situation?
>> OK, in Diamond inheritance in Python (and all multi-inheritance is
>> diamond-shaped in Python), the common ancestor must have a method
>> in order to properly use super.  The mro is guaranteed to have the
>> top of the split (C below) before its children in the mro, and the
>> join point (object or root below) after all of the classes from
>> which it inherits.
>>
>> So, the correct way to do what you want:
>>    class A:
>>        def __init__(self):
>>            super().__init__()
>>            print('A')
>>
>>    class B:
>>        def __init__(self):
>>            super().__init__()
>>            print('B')
>>
>>    class C(A, B):
>>        def __init__(self):
>>            super().__init__()
>>            print('C')
>>
>>    C()
>>
>> And, if you are doing it with a message not available in object:
>>
>>    class root:
>>        def prints(self):
>>            print('root') # or pass if you prefer
>>
>>    class A(root):
>>        def prints(self):
>>            super().prints()
>>            print('A')
>>
>>    class B(root):
>>        def prints(self):
>>            super().prints()
>>            print('B')
>>
>>    class C(A, B):
>>        def prints(self):
>>            super().prints()
>>            print('C')
>>
>>    C().prints()
>>
>> --Scott David Daniels
>> Scott.Daniels at Acm.Org
>>
> 
> Great explanation, and 1/2 a "duh" to me. Thanks.
> What I was missing is that each path up to and including the top of the diamond
> must include a definition of the method, along with super() calls to move the method
> calling on its way up. Is this what the documentation means by
> "cooperative multiple inheritance"?
I expect so.

> ... Again, many thanks for the quick and clear response.
Since you know exactly what is confusing right now, and
what the resolution is, could I lean on you to take a stab
at improving the explanation?  I think I know what the
solution is, but I don't have a good handle on what needs
explaining and what is easily understood.  If you do something,
others can fix it where it doesn't work.

--Scott David Daniels
Scott.Daniels at Acm.Org




More information about the Python-list mailing list