[Python-ideas] [Python-Dev] python and super

Carl Meyer carl at oddbird.net
Fri Apr 15 20:17:11 CEST 2011


Hi Mike,

On 04/15/2011 01:00 PM, Mike Graham wrote:
> On Fri, Apr 15, 2011 at 12:42 PM, Carl Meyer <carl at oddbird.net> wrote:
>> ...
>> Consider these classes:
>>
>> class UncooperativeBase:
>>    def method(self):
>>        # look Ma, no super() call!
>>        return ["UncooperativeBase"]
>>
>>
>> class OtherBase:
>>    def method(self):
>>        return ["OtherBase"] + super().method()
>>
>>
>> class Child(UncooperativeBase):
>>    def method(self):
>>        return ["Child"] + super().method()
>>
>>
>> class GrandChild(Child, OtherBase):
>>    def method(self):
>>        return ["GrandChild"] + super().method()
>>
>>
>> Currently, OtherBase.method() is never called, because
>> UncooperativeBase.method() breaks the super() chain. Any proposal to
>> have super() ensure that OtherBase.method() is called needs to explain
>> what exactly happens to its return value. This would normally be handled
>> explicitly by UncooperativeBase, since it would call super() and do
>> something with the return value. But with the explicit chain broken, you
>> end up with two different chains, and at some point their return values
>> would need integrating.
>>
>> Carl
> 
> I feel like you're implying this would be fixed by having
> UncooperativeBase call super().method(), but this would not make
> working code. _It's the base class's responsibility *not* to call
> super._
> 
> If UncooperativeBase called super() and we called
> GrandChild().method(), then we would call our three superclasses's
> method methods and object's. the problem is that object doesn't even
> HAVE a method method, so we'll get an error. (For the very common
> example of __init__, object *IS* the shared superless base class with
> the method we want, but we need our own shared superless base class
> for arbitrary methods.)

That's right, though only distantly related to my point. I was just too
aggressive in cutting the example down to a minimal number of classes;
UncooperativeBase and OtherBase should share a superclass with method(),
call it GrandParent.

My point still applies the same: if UncooperativeBase doesn't call
super().method(), it's not feasible for super to call OtherBase.method()
(the "call siblings anyway" feature that's been requested in this
thread), because it would introduce the need to somehow magically
"integrate" the return values from OtherBase.method() and
UncooperativeBase.method().

> This isn't a problem I know a technical solution to—we can't have two
> independent base classes with the same method. If they are related to
> each other, they need to share a base class that probably doesn't do
> anything exciting. If they're truly unrelated, then we don't want to
> be calling them interchangeably in the MRO and we need to give them
> different names, perhaps using a proxy class with one that calls into
> the other.

Right. This (unrelated base classes with the same method) was just an
error in my example, not a problem I am trying to propose a solution to.

> Another solution that is much cleaner is to use composition for one or
> both of the classes involved. This only works if these are concrete
> classes, obviously, but gets us tons of benefits. It's not at all
> complicated to decide what needs to be called when, change names, or
> pick-and-choose what functionality to re-use.

Agreed.

Carl



More information about the Python-ideas mailing list