[Python-3000] [Fwd: features i'd like [Python 3000] ... #3: fix super()]
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
_method = super(cls, obj).method
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.
More information about the Python-3000