[Python-3000] [Fwd: features i'd like [Python 3000] ... #3: fix super()]

Josiah Carlson jcarlson at uci.edu
Thu Dec 7 02:47:21 CET 2006


"Thomas Wouters" <thomas at python.org> wrote:
> On 12/6/06, Josiah Carlson <jcarlson at uci.edu> wrote:
> > "Thomas Wouters" <thomas at python.org> wrote:
> > > You forget that that's actually what super() is for. It does the right
> > thing
> > > in the case of MI (and every other case, in fact :-)
> >
> > Except for this one:
> >
> > >>> class foo(object):
> > ...     pass
> > ...
> > >>> class bar(foo):
> > ...     def method(self):
> > ...         super(bar, self).method()
> > ...
> > >>> bar().method()
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in ?
> >   File "<stdin>", line 3, in method
> > AttributeError: 'super' object has no attribute 'method'
> > >>>
> 
> 
> I'm not sure what makes you say that. There is no superclass method
> 'method', so 'AttributeError' seems like the Right Thing to me.

I agree with you, but it makes it *very* difficult to write properly
behaving cooperative super calls.  In fact, if one inherits at any point
from object, one must necessarily use the following pattern in every
class:

try:
    _method = super(cls, obj).method
except AttributeError:
    pass
else:
    result = _method(...)

How is this reasonable or from an "I want to write correct code"
standpoint?  I would argue that it isn't reasonable, and is in fact
insane.  I don't want to write that, but to prevent AttributeErrors from
cropping up in arbitrary locations, it is necessary.


> > Because of this kind of thing, I do my best to never produce code that
> > has a diamond inheritance structure (except for object), and always use
> > things like foo.method(self).
> 
> 
> Which would have given you the same AttributeError.

No it wouldn't have, because I wouldn't have written foo.method(self)
bar.method().  I was using it as an example of class.method(self)
calling semantics.  I am ([un]fortunately) anal-retentive enough to
pre-check my calls.


> If you want co-operative MI classes, you need to do more than just use
> super(): you need a baseclass that provides the 'interface', if you will,
> that you wish to co-operate in. For many of the standard __hooks__, object

Certainly that is a solution, but it kills one of the major uses of
multiple inheritance: mixins.  Not all mixin classes subclass from the
*one and only one base class that doesn't call super*.  An example of
such is in the standard library; SocketServer and its derivatives (or
whatever it is, I can never remember). I think about the only thing in
common is perhaps their subclassing of object.

> Avoiding MI is certainly a good option, provided you're able to enforce that
> policy somehow.

Actually, I use MI quite often, I just verify that I never have a
diamond inheritance with anything other than object.  For example:

class A(X): pass
class B(A): pass
class C(A): pass
class D(B, C): pass

I never do the above unless I *know* that X is object, because then I
*know* that in D.meth(self) I can use B.meth(self) and C.meth(self)
(assuming that D, B, and C all implement a .meth() method).  But again,
I find that being anal-retentive is easier and faster than fighting with
super() and its semantics.


 - Josiah



More information about the Python-3000 mailing list