[Python-Dev] Re: super() harmful?
James Y Knight
foom at fuhm.net
Thu Jan 6 00:00:38 CET 2005
On Jan 5, 2005, at 1:23 PM, Guido van Rossum wrote:
>> The issue of mixing super() and explicit calls to the superclass's
>> method occur with any method. (Thus making it difficult/impossible for
>> a framework to convert to using super without breaking client code
>> that
>> subclasses).
>
> Well, client classes which are leaves of the class tree can still
> safely use BaseClass.thisMethod(self, args) -- it's only classes that
> are written to be extended that must all be converted to using
> super(). So I'm not sure how you think your clients are breaking.
See the section "Subclasses must use super if their superclasses do".
This is particularly a big issue with __init__.
>> Adding optional arguments to one branch of the inheritance tree, but
>> not another, or adding different optional args in both branches.
>> (breaks unless you always pass optional args as keywordargs, and all
>> methods take **kwargs and pass that on to super).
>
> But that breaks anyway; I don't see how using the old
> Base.method(self, args) approach makes this easier, *unless* you are
> using single inheritance. If you're expecting single inheritance
> anyway, why bother with super()?
There is a distinction between simple multiple inheritance, which did
work in the old system vs. multiple inheritance in a diamond structure
which did not work in the old system. However, consider something like
the following (ignore the Interface/implements bit if you want. It's
just to point out a common situation where two classes can
independently implement the same method without having a common
superclass):
class IFrob(Interface):
def frob():
"""Frob the knob"""
class A:
implements(IFrob)
def frob(self, foo=False):
print "A.frob(foo=%r)"%foo
class B:
implements(IFrob)
def frob(self, bar=False):
print "B.frob(bar=%r)"%bar
class C(A,B):
def m(self, foo=False, bar=False):
A.m(self, foo=foo)
B.m(self, bar=bar)
print "C.frob(foo=%r, bar=%r)"%(foo,bar)
Now, how do you write that to use super? Here's what I come up with:
class IFrob(Interface):
def frob():
"""Frob the knob"""
class A(object):
implements(IFrob)
def frob(self, foo=False, *args, **kwargs):
try:
f = super(A, self).frob
except AttributeError:
pass
else:
f(foo=foo, *args, **kwargs)
print "A.frob(foo=%r)"%foo
class B(object):
implements(IFrob)
def frob(self, bar=False, *args, **kwargs):
try:
f = super(B, self).frob
except AttributeError:
pass
else:
f(bar=bar, *args, **kwargs)
print "B.frob(bar=%r)"%bar
class C(A,B):
def frob(self, foo=False, bar=False, *args, **kwargs):
super(C, self).frob(foo, bar, *args, **kwargs)
print "C.frob(foo=%r, bar=%r)"%(foo,bar)
> And using multiple inheritance the old was was not confusing? Surely
> you are joking.
It was pretty simple until you start having diamond structures. Then
it's complicated. Now, don't get me wrong, I think that MRO-calculating
mechanism really is "the right thing", in the abstract. I just think
the way it works out as implemented in python is really confusing and
it's easy to be worse off with it than without it.
> If they're happy with single inheritance, let them use super()
> incorrectly. It works, and that's what count. Their code didn't work
> right with multiple inheritance before, it still doesn't. Some people
> just are uncomfortable with calling Base.method(self, ...) and feel
> super is "more correct". Let them.
Their code worked right in M-I without diamonds before. Now it likely
doesn't work in M-I at all.
James
More information about the Python-Dev
mailing list