Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

super() doesn't get superclass

20 views
Skip to first unread message

Ben Finney

unread,
Sep 18, 2007, 12:15:25 AM9/18/07
to
Howdy all,

After banging my head against super() trying to reliably get
attributes of a superclass, I gained a little enlightenment when this
turned up in a search:

"Python's Super is nifty, but you can't use it
(Previously: Python's Super Considered Harmful)"
<URL:http://fuhm.org/super-harmful/>

An early paragraph stood out that made my current problems clear:

One big problem with 'super' is that it sounds like it will cause
the superclass's copy of the method to be called. This is simply
not the case, it causes the next method in the MRO to be called.

Oh. The author's right, I got that mistaken impression too. Obviously,
then, I must have misread the documentation of 'super'. I went back to
double-check, and was appalled to find:

super(type[, object-or-type])
Return the superclass of type. [...]

<URL:http://docs.python.org/lib/built-in-funcs.html#l2h-72>

Why does the documentation of 'super' say that it returns the
superclass when *that's not true*? It doesn't return the superclass,
it returns the next class in the MRO, whether that's a superclass or
not.

Actually, even that's not true. The error message "AttributeError:
'super' object has no attribute 'bazfunc'" makes it clear that 'super'
actually returns not the superclass, but a 'super' object, whatever
that's supposed to be.


After reading the rest of the article, I'm amazed that 'super' as
currently implemented is in Python at all. I agree with the author
that it's useless unless *everyone* uses it for *everything*, and even
then it's pretty limited.

One thing's for sure, it's badly misnamed, and falsely documented.

Can anyone point me to a counter-argument to the above article?

--
\ "The World is not dangerous because of those who do harm but |
`\ because of those who look at it without doing anything." |
_o__) —Albert Einstein |
Ben Finney

Evan Klitzke

unread,
Sep 18, 2007, 12:42:41 AM9/18/07
to pytho...@python.org
On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
> Howdy all,
>
> After banging my head against super() trying to reliably get
> attributes of a superclass, I gained a little enlightenment when this
> turned up in a search:
>
> "Python's Super is nifty, but you can't use it
> (Previously: Python's Super Considered Harmful)"
> <URL:http://fuhm.org/super-harmful/>
>
> An early paragraph stood out that made my current problems clear:
>
> One big problem with 'super' is that it sounds like it will cause
> the superclass's copy of the method to be called. This is simply
> not the case, it causes the next method in the MRO to be called.
>
> Oh. The author's right, I got that mistaken impression too. Obviously,
> then, I must have misread the documentation of 'super'. I went back to
> double-check, and was appalled to find:
>
> super(type[, object-or-type])
> Return the superclass of type. [...]
>
> <URL:http://docs.python.org/lib/built-in-funcs.html#l2h-72>
>
> Why does the documentation of 'super' say that it returns the
> superclass when *that's not true*? It doesn't return the superclass,
> it returns the next class in the MRO, whether that's a superclass or
> not.

The next class in the MRO _is_ a superclass. Maybe not the way you've
defined it in your own code, but certainly of the new class you created
with MI.

> Actually, even that's not true. The error message "AttributeError:
> 'super' object has no attribute 'bazfunc'" makes it clear that 'super'
> actually returns not the superclass, but a 'super' object, whatever
> that's supposed to be.

No, super really does return a class. What makes you think that super
returns a special sort of object?

> After reading the rest of the article, I'm amazed that 'super' as
> currently implemented is in Python at all. I agree with the author
> that it's useless unless *everyone* uses it for *everything*, and even
> then it's pretty limited.

I don't see what the problem is. If you don't use super, then you can
break the inheritance chain, but this is no different than calling
superclass methods by passing in self (i.e. the old-style way of doing
it), and in fact using super is far more flexible. There's no way to
magically know when to call the superclass' method, and even if you knew
when, there's no way to magically know when it needs to be called.

If you're using multiple inheritance, and you're _not_ using super
everywhere, then your code is broken anyway. Use super correctly in your
own code, and you don't need to worry about other people using it
incorrectly.

--
Evan Klitzke <ev...@yelp.com>

Ben Finney

unread,
Sep 18, 2007, 1:24:21 AM9/18/07
to
Evan Klitzke <ev...@yelp.com> writes:

> On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
> > Why does the documentation of 'super' say that it returns the
> > superclass when *that's not true*? It doesn't return the
> > superclass, it returns the next class in the MRO, whether that's a
> > superclass or not.
>
> The next class in the MRO _is_ a superclass. Maybe not the way
> you've defined it in your own code, but certainly of the new class
> you created with MI.

If I define a class hierarchy as follows::

class A(object): pass
class B(object): pass
class C(A): pass
class D(B): pass

is it true to say that "D is a superclass of A"? No, because they're
entirely unrelated except that they inherit from 'object'. The
superclass of 'A' is 'object'.

How about this:

class E(C, D): pass

In this instance, the MRO now has D following A; but the superclass of
'A' is still 'object'.

You seem to be saying that now suddenly D *is* a superclass of
A. That's certainly not what users will think of when they think
"superclass" though.

> > Actually, even that's not true. The error message "AttributeError:
> > 'super' object has no attribute 'bazfunc'" makes it clear that
> > 'super' actually returns not the superclass, but a 'super' object,
> > whatever that's supposed to be.
>
> No, super really does return a class. What makes you think that
> super returns a special sort of object?

>>> super(A)
<super: <class 'A'>, NULL>
>>> super(A).__class__
<type 'super'>

What I expect, incidentally, is that a function documented as "returns
the superclass of 'type'" would actually return that class (in this
case, the type 'object'), not an object of 'super' type.

> > After reading the rest of the article, I'm amazed that 'super' as
> > currently implemented is in Python at all. I agree with the author
> > that it's useless unless *everyone* uses it for *everything*, and
> > even then it's pretty limited.
>
> I don't see what the problem is. If you don't use super, then you can
> break the inheritance chain

I don't want to break the inheritance chain. I want the superclass,
not the "next class in the MRO".

Orthogonally to that, I think it's madness to write a function for
"return the next class in the MRO for 'type'" and document it as
"return the superclass of 'type'".

Am I mistaken in thinking that "superclass of foo" is equivalent to
"parent class of foo"? If so, I'd lay heavy odds that I'm not alone in
that thinking.

--
\ "Laugh and the world laughs with you; snore and you sleep |
`\ alone." —anonymous |
_o__) |
Ben Finney

Alex Martelli

unread,
Sep 18, 2007, 1:31:40 AM9/18/07
to
Ben Finney <bignose+h...@benfinney.id.au> wrote:

> Am I mistaken in thinking that "superclass of foo" is equivalent to
> "parent class of foo"? If so, I'd lay heavy odds that I'm not alone in
> that thinking.

"That thinking" (confusing "parent" with "ancestor") makes sense only
(if at all) in a single-inheritance world. Python's super() exists to
support MULTIPLE inheritance.

In general, "a superclass of foo" means "a class X such that foo is a
sublass of X" and thus applies to all parents, all parents of parents,
and so on ("issubclass" does NOT mean "is a DIRECT AND IMMEDIATE
subclass", but "is a subclass"; check the Python builtin function of
that name).


Alex

Ben Finney

unread,
Sep 18, 2007, 1:38:46 AM9/18/07
to
Evan Klitzke <ev...@yelp.com> writes:

> If you're using multiple inheritance, and you're _not_ using super
> everywhere, then your code is broken anyway.

This seems to support the notion that 'super' is unusable. If I
inherit from code that isn't under my control, and then use super(),
my code is broken.

Therefore, to avoid writing broken code, I must either never inherit
from code not under my control, or I must never use super(). Since the
former is practically unavoidable, I must choose the latter.

Which, naturally, compounds the problem, since when someone else uses
*my* code, they in turn must conclude that they can't use super().

> Use super correctly in your own code, and you don't need to worry
> about other people using it incorrectly.

As the article points out, when using super(),

you must remember that super does not call your superclass. You
must be prepared to call any other class's method in the hierarchy
and be prepared to be called from any other class's method.

So, the programmer using super() very much *does* need to worry about
other people using it correctly.

--
\ "Quidquid latine dictum sit, altum viditur." ("Whatever is |
`\ said in Latin, sounds profound.") -- Anonymous |
_o__) |
Ben Finney

Ben Finney

unread,
Sep 18, 2007, 1:41:30 AM9/18/07
to
al...@mac.com (Alex Martelli) writes:

> In general, "a superclass of foo" means "a class X such that foo is a
> sublass of X"

Sure. However, this doesn't equate to the assertion that "next class
in the MRO is the superclass", which is what I was responding to.

--
\ "Even if the voices in my head are not real, they have pretty |
`\ good ideas." —anonymous |
_o__) |
Ben Finney

Message has been deleted

Carl Banks

unread,
Sep 18, 2007, 6:22:00 AM9/18/07
to
On Tue, 18 Sep 2007 15:38:46 +1000, Ben Finney wrote:
> Evan Klitzke <ev...@yelp.com> writes:
>
>> If you're using multiple inheritance, and you're _not_ using super
>> everywhere, then your code is broken anyway.
>
> This seems to support the notion that 'super' is unusable. If I inherit
> from code that isn't under my control, and then use super(), my code is
> broken.
>
> Therefore, to avoid writing broken code, I must either never inherit
> from code not under my control, or I must never use super(). Since the
> former is practically unavoidable, I must choose the latter.
>
> Which, naturally, compounds the problem, since when someone else uses
> *my* code, they in turn must conclude that they can't use super().

I'm sorry, but you can't inherit from someone else's classes and not
worry about what they're doing. Whether they use super or not is only
one possible concern. It's not like the super destroyed the magical
utopia where you could derive from other people's classes without worry.

In any case, it's just as problematic if you don't use super and your
base classes do. By your logic, your code is "broken" no matter what you
do, and so the only "conclusion" you can come to is never to derive from
classes that aren't under your control.

(Which, frankly, isn't all that bad a conclusion. In 8 years of Python
programming, I've inherited from exactly one class that wasn't under my
control: Thread. It's not "practically impossible" to avoid, at least
not for me.)


>> Use super correctly in your own code, and you don't need to worry about
>> other people using it incorrectly.
>
> As the article points out, when using super(),
>
> you must remember that super does not call your superclass. You must
> be prepared to call any other class's method in the hierarchy and be
> prepared to be called from any other class's method.
>
> So, the programmer using super() very much *does* need to worry about
> other people using it correctly.

Yes. Welcome to programming.


Carl Banks

Message has been deleted

Hrvoje Niksic

unread,
Sep 18, 2007, 11:41:46 AM9/18/07
to
Bruno Desthuilliers <bruno.42.de...@wtf.websiteburo.oops.com> writes:

> If a class X is in the MRO of call Y, then X is a superclass of Y. I
> agree that the documentation for super is somewhat misleading (and
> obviously wrong), but it still *give access to* (at least one of)
> the superclass(es).

I believe the confusion comes from different assumptions about what
"superclasses" refers to. super() iterates over superclasses of the
*instance* in use, but an individual call to super does not
necessarily invoke the superclass of the *implementation* of the
method. For example, given a random class:

class X(Y):
def foo(self):
super(X, self).foo()

...there is in fact no guarantee that super() calls a superclass of
X. However, it is certainly guaranteed that it will call a superclass
of type(self).

Pre-2.2 Python used a simpler scheme where the superclass was always
called, but it caused problems with diamond inheritance where some
methods would be called either twice or not at all. (This is
explained in http://www.python.org/download/releases/2.2.3/descrintro/
in some detail.)

Ben Finney

unread,
Sep 18, 2007, 7:11:37 PM9/18/07
to
Bruno Desthuilliers <bruno.42.de...@wtf.websiteburo.oops.com> writes:

> Ben Finney a écrit :


> > Evan Klitzke <ev...@yelp.com> writes:
> >> On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:

> >>> [the 'super' function] doesn't return the superclass, it returns


> >>> the next class in the MRO, whether that's a superclass or not.
> >> The next class in the MRO _is_ a superclass.
> >

> > [demonstration that the next class in the MRO is not necessarily a
> > superclass]


> >
> > You seem to be saying that now suddenly D *is* a superclass of
> > A.
>

> I don't see such an assertion in Evan's answer. Chapter and verse
> ???

I've trimmed the quoting to make it clearer.

Evan is claiming that "the next class in the MRO _is_ a superclass",
apparently by his definition or some other that I've not seen.

I've shown a fairly simple multiple-inheritance hierarchy where the
next class in the MRO is not an ancestor of the subject class, but is
instead a class that merely shares a common ancestor.

Either "superclass of A" is equivalent to "ancestor class of A", or
it's not. I maintain that many programmers will expect that it is, but
Evan's assertion says otherwise. It can't be both.

> > That's certainly not what users will think of when they think
> > "superclass" though.
>

> If a class X is in the MRO of call Y, then X is a superclass of Y.

That goes completely against what Alex Martelli told me, which was
that "superclass" can be thought of as synonymous with "ancestor".

> I agree that the documentation for super is somewhat misleading (and
> obviously wrong),

Well, that's the first time someone has acknowledged that in this
thread, so I guess this is something.

> but it still *give access to* (at least one of) the superclass(es).

Only if you allow "some class somewhere in the inheritance tree, even
one this class never inherited from directly or indirectly" to be in
the definition of "superclass".

I'm arguing that what people mean by "superclass" is "a direct or
indirect ancestor class", and it's highly misleading to imply that by
the function name what that's not what the function does.

> >>> After reading the rest of the article, I'm amazed that 'super'
> >>> as currently implemented is in Python at all.
>

> If you have a better solution for handling multiple inheritence,
> please share with us.

My concern is to at least not *directly mislead* the programmer
through a badly-named function. If 'super' can invoke a non-superclass
— if instead it gets "the next class in the MRO" — then this is at the
least badly-named.

> FWIW, after all the articles I've read explaining why Python is
> badly designed, badly implemented, and totally flawed, I do wonder
> why this language exists at all !-)

In most of those arguments I'm firmly on the side of the Python
designers. Not on this one.

> > I don't want to break the inheritance chain. I want the
> > superclass,
>

> A soon as you have either multiple inheritence and/or an inheritence
> tree with depth > 1, there's no such thing as "the" superclass. wrt/
> your exemple, object, A, B, C and D are *all* superclasses of E.

Yes, they are. But my example was not "get the superclass of E", but
"get the superclass of A".

The *only* ancestor of 'A' in the example is 'object', so I expect
"superclass of A" to *always* get 'object'. But that's not what
happens!

Instead, it *sometimes* gets 'object', and *sometimes* gets 'D' —
depending on who has inherited from a class that isn't even 'A'!
That's what makes 'super' definitely misnamed, and practically
unusable.

> The next class in the MRO is (usually and AFAICT) the most direct
> superclass.

Demonstrably not, in the examples given in
<URL:http://fuhm.org/super-harmful/>.

> I wouldn't use such an extreme word as 'madness', but I totally agree
> that this should be corrected. Care to submit a doc patch ?

I don't understand what practical uses 'super' is intended for (only
that they don't seem to match any of my needs), so the only
replacement I would come up with would not be constructive.

--
\ "A computer once beat me at chess, but it was no match for me |
`\ at kick boxing." -- Emo Philips |
_o__) |
Ben Finney

Ben Finney

unread,
Sep 18, 2007, 7:14:15 PM9/18/07
to
Hrvoje Niksic <hni...@xemacs.org> writes:

> class X(Y):
> def foo(self):
> super(X, self).foo()
>
> ...there is in fact no guarantee that super() calls a superclass of
> X. However, it is certainly guaranteed that it will call a superclass
> of type(self).

Not even that. It could call *any class in the inheritance hierarchy*,
depending on how the MRO has resolved "next class". Even one that is
neither an ancestor nor a descendant of X.

--
\ "When I was a kid I used to pray every night for a new bicycle. |
`\ Then I realised that the Lord doesn't work that way so I stole |
_o__) one and asked Him to forgive me." -- Emo Philips |
Ben Finney

Message has been deleted

Michele Simionato

unread,
Sep 19, 2007, 1:13:12 AM9/19/07
to

You are right, I think I even filed a documentation bug for
that years ago, and I wrote an entire paper on the subject that
however I never published since I never felt 100% confident
with super (and I had other fishes to fry ;)
I realize now that I was wrong in not publishing it.
You can find the draft (warning: it is a draft, I did
not check the examples there, they are likely broken)
here:

http://www.phyast.pitt.edu/~micheles/python/super.html

It begins as follows:

"""
The truth about super
Author: Michele Simionato
Date: June 2004
Status: Draft

super is a new built-in, first introduced in Python 2.2 and slightly
improved and fixed in Python 2.3, which is little known to the average
Python programmer. One of the reason for this fact is its poor
documentation`: at the time of this writing (June 2004) super
documentation is incomplete and in some parts misleading and even
wrong. For instance, it was recently pointed out on comp.lang.python


that the standard library (Python 2.3.4, section 2.1) still says:

super(type[, object-or-type])
Return the superclass of type. If the second argument is omitted
the
super object returned is unbound. If the second argument is an
object,
isinstance(obj, type) must be true. If the second argument is a
type,
issubclass(type2, type) must be true. super() only works for new-
style
classes.

The first sentence is just plain wrong. super does not return the
superclass. There is no such a thing as "the" superclass in a Multiple
Inheritance (MI) language. Also, the sentence about 'unbound' is
misleading, since it may easily lead the programmer to think about
bound and unbound methods, whereas it has nothing to do with that
concept. Finally, there subtle pitfalls of super which are not at all
mentioned. IMNSHO super is one of the most trickiest and surprising
Python constructs, so it absolutely needs a document to share light on
some of his secrets: the present article aims to fix the issues with
the current documentation, and tell you the "truth" about super. At
least the amount of truth I have discovered with my experimentations,
which is certainly not the whole truth ;)

Here is the plan: first I will discuss the concept of superclass in a
Multiple Inheritance (MI) world (there is no such a thing as "the"
superclass!); second, I will show that super is a proxy object, able
to dispatch to the right methods/attributes in the MRO; third,

recall some background on how the resolution of methods works on how
descriptors work and (essentially pointing out to the standard
references); then I will discuss the more common invocation of super -
the invocation with two arguments - and finally I will discuss the
most tricky part, i.e. invoking super with just one argument and I
will discuss pitfalls.

Finally, a fair warning: this document is aimed to expert Pythonistas.
It is not for the faint of heart ;)
"""

Ben Finney

unread,
Sep 19, 2007, 1:48:08 AM9/19/07
to
Dennis Lee Bieber <wlf...@ix.netcom.com> writes:

> Try to interpret it as:

My point exactly. If a function is named 'super' and operates on
classes, it's a pretty strong implication that it's about
superclasses. Any explanation that begins "Try to interpret it as" and
then goes on to explain that it's to do with MRO, *not* superclasses,
is evidence that the function is *badly named*.

I'm not interested in documenting this function, because as I said I
don't see why I would want to use it. My objection is that, as
currently named, it's an *obstacle* when a programmer goes looking for
a way to get a superclass.

Possibly the name 'next_in_mro', while ugly, would at least match the
actual behaviour of this function.

At least then the next person who goes looking for "how do I get the
superclass of A?" won't be misled into trying to use *the wrong
function for that purpose*.

--
\ "If you can't annoy somebody there is little point in writing." |
`\ -- Kingsley Amis |
_o__) |
Ben Finney

Paul Rudin

unread,
Sep 19, 2007, 2:50:41 AM9/19/07
to
Ben Finney <bignose+h...@benfinney.id.au> writes:


> Possibly the name 'next_in_mro', while ugly, would at least match the
> actual behaviour of this function.

In common lisp there's (call-next-method ...)

Hrvoje Niksic

unread,
Sep 19, 2007, 3:22:36 AM9/19/07
to
Ben Finney <bignose+h...@benfinney.id.au> writes:

> Hrvoje Niksic <hni...@xemacs.org> writes:
>
>> class X(Y):
>> def foo(self):
>> super(X, self).foo()
>>
>> ...there is in fact no guarantee that super() calls a superclass of
>> X. However, it is certainly guaranteed that it will call a superclass
>> of type(self).
>
> Not even that. It could call *any class in the inheritance
> hierarchy*,

The inheritance hierarchiy is populated by the various (direct and
indirect) superclasses of type(self).

> depending on how the MRO has resolved "next class". Even one that is
> neither an ancestor nor a descendant of X.

My point exactly. superclass of X is not the same as superclass of
type(self). Super iterates over the latter, where you expect the
former.

Hrvoje Niksic

unread,
Sep 19, 2007, 3:31:57 AM9/19/07
to
Ben Finney <bignose+h...@benfinney.id.au> writes:

> Evan is claiming that "the next class in the MRO _is_ a superclass",
> apparently by his definition or some other that I've not seen.

The definition of superclass is not the issue, the issue is
"superclass *of which class*"? You expect super(A, self) to iterate
only over superclasses of A, even when self is an instance of a
subtype of A. What really happens is that super(A, self) yields the
next method in type(self)'s MRO, which can and does cause include
classes that are not by any definition superclasses of A. All of
those classes are, however, superclasses of the instance's type.

I think it is not possible to have super(A, self) only call
superclasses of A and at the same time having multiple inheritance
work without calling some methods in the hierarchy twice or not at
all. Guido's paper at http://tinyurl.com/qkjgp explains the reasoning
behind super in some detail.

>> I agree that the documentation for super is somewhat misleading (and
>> obviously wrong),
>
> Well, that's the first time someone has acknowledged that in this
> thread, so I guess this is something.

For the record, I also agree with that. The documentation should
document in some detail that super(type, obj) yields superclasses of
type(obj), not of type, and that the "type" argument is only used for
super to be able to locate the next type in the list.

>> I wouldn't use such an extreme word as 'madness', but I totally agree
>> that this should be corrected. Care to submit a doc patch ?
>
> I don't understand what practical uses 'super' is intended for

It's intended for cooperative multiple inheritance, a la CLOS's
call-next-method.

Bruno Desthuilliers

unread,
Sep 19, 2007, 6:36:29 AM9/19/07
to
Ben Finney a écrit :

> Bruno Desthuilliers <bruno.42.de...@wtf.websiteburo.oops.com> writes:
>
>> Ben Finney a écrit :
>>> Evan Klitzke <ev...@yelp.com> writes:
>>>> On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
>>>>> [the 'super' function] doesn't return the superclass, it returns
>>>>> the next class in the MRO, whether that's a superclass or not.
>>>> The next class in the MRO _is_ a superclass.
>>> [demonstration that the next class in the MRO is not necessarily a
>>> superclass]
>>>
>>> You seem to be saying that now suddenly D *is* a superclass of
>>> A.
>> I don't see such an assertion in Evan's answer. Chapter and verse
>> ???
>
> I've trimmed the quoting to make it clearer.
>
> Evan is claiming that "the next class in the MRO _is_ a superclass",
> apparently by his definition or some other that I've not seen.

The next class in the MRO *is* a superclass of the *instance*. Else it
wouldn't be in the MRO !-)

> I've shown a fairly simple multiple-inheritance hierarchy where the
> next class in the MRO is not an ancestor of the subject class,

It's an ancestor of the class of the instance on which the method is
called.

> Either "superclass of A" is equivalent to "ancestor class of A", or
> it's not. I maintain that many programmers will expect that it is, but
> Evan's assertion says otherwise. It can't be both.
>
>>> That's certainly not what users will think of when they think
>>> "superclass" though.
>> If a class X is in the MRO of call Y, then X is a superclass of Y.

s/call/class/, of course.


> That goes completely against what Alex Martelli told me, which was
> that "superclass" can be thought of as synonymous with "ancestor".

Pardon ???

I repeat: if class X is in the MRO of class Y, then X is a superclass of
class Y. Which indeed makes X an ancestor of Y.

>> I agree that the documentation for super is somewhat misleading (and
>> obviously wrong),
>
> Well, that's the first time someone has acknowledged that in this
> thread, so I guess this is something.

OTHO, I don't think anyone here stated that the doc was right !-)

>> but it still *give access to* (at least one of) the superclass(es).
>
> Only if you allow "some class somewhere in the inheritance tree, even
> one this class never inherited from directly or indirectly" to be in
> the definition of "superclass".

By definition, if the class is in the inheritence tree, then this class
is inherited from directly or indirectly. FWIW, I've never caught
super() calling a class that was not in the inheritence tree of the
instance passed to it... If you noticed such a thing, then by all mean
fill a bug report.

> I'm arguing that what people mean by "superclass" is "a direct or
> indirect ancestor class", and it's highly misleading to imply that by
> the function name what that's not what the function does.

Please remember that super() is usually called with *2* arguments : the
class in which the method is defined (let's call this class C), *and* an
instance. This instance may be an instance of a *subclass* of C. So the
MRO to consider is the MRO *of the instance*. Else, super would be
totally useless.

>>>>> After reading the rest of the article, I'm amazed that 'super'
>>>>> as currently implemented is in Python at all.
>> If you have a better solution for handling multiple inheritence,
>> please share with us.
>
> My concern is to at least not *directly mislead* the programmer
> through a badly-named

Or badly documented

> function

class. super is not a function, it's a class.

> If 'super' can invoke a non-superclass

super won't never "invoke" anything that's not in the MRO of the
*instance* passed to it.

> — if instead it gets "the next class in the MRO" — then this is at the
> least badly-named.

Possibly, but this is another point.

>> FWIW, after all the articles I've read explaining why Python is
>> badly designed, badly implemented, and totally flawed, I do wonder
>> why this language exists at all !-)
>
> In most of those arguments I'm firmly on the side of the Python
> designers. Not on this one.

Well, I understand that you disagree with both the documention and the
name of super. As far as I'm concerned, the mere fact that this
discussion happens is probably a sign that there's something to be fixed
here - at least wrt documentation, possibly wrt/ naming. But the
*feature* by itself is certainly something we do want to keep, whatever
some may argue.

>>> I don't want to break the inheritance chain. I want the
>>> superclass,
>> A soon as you have either multiple inheritence and/or an inheritence
>> tree with depth > 1, there's no such thing as "the" superclass. wrt/
>> your exemple, object, A, B, C and D are *all* superclasses of E.
>
> Yes, they are. But my example was not "get the superclass of E", but
> "get the superclass of A".

You wrote:

"""
If I define a class hierarchy as follows::

class A(object): pass
class B(object): pass
class C(A): pass
class D(B): pass

is it true to say that "D is a superclass of A"? No, because they're
entirely unrelated except that they inherit from 'object'. The
superclass of 'A' is 'object'.

How about this:

class E(C, D): pass

In this instance, the MRO now has D following A; but the superclass of
'A' is still 'object'.
"""

If I understand correctly, your concerns are with the superclass*es* of
E, not with the superclass of A.

> The *only* ancestor of 'A' in the example is 'object',

Yes.

> so I expect
> "superclass of A" to *always* get 'object'. But that's not what
> happens!

superclass of A is object, no problem. But the next (according to the
MRO you defined) superclass of an instance of E is not necessarily A...

> Instead, it *sometimes* gets 'object', and *sometimes* gets 'D' —
> depending on who has inherited from a class that isn't even 'A'!
> That's what makes 'super' definitely misnamed,

Badly documented, and (very) possibly (as this whole thread illustrates)
misnamed...

> and practically
> unusable.

And perfectly usable. At least once you understand what it's for.

>> The next class in the MRO is (usually and AFAICT) the most direct
>> superclass.
>
> Demonstrably not, in the examples given in
> <URL:http://fuhm.org/super-harmful/>.
>
>> I wouldn't use such an extreme word as 'madness', but I totally agree
>> that this should be corrected. Care to submit a doc patch ?
>
> I don't understand what practical uses 'super' is intended for

There's a whole article on it on python.org:
http://www.python.org/download/releases/2.2/descrintro/#cooperation

The goal is to call the correct "next" method according to MRO. Indeed,
it could have been name "call_next_method".

> (only
> that they don't seem to match any of my needs),

If all you want is to get at the direct ancestor of the *class* in wich
a method is defined, the solution is well-known and quite obvious: call
this class directly. ie:

class A(object):
def __init__(self):
print "A.__init__"

class B(object):
def __init__(self):
A.__init__(self)
print "B.__init__"


Note that in this case, you'll get exactly the same result with :

class B(object):
def __init__(self):
super(B, self).__init__()
print "B.__init__"


super is only useful when MI comes in play - which BTW is not that
common in Python.

Michele Simionato

unread,
Sep 19, 2007, 6:52:14 AM9/19/07
to
On Sep 19, 12:36 pm, Bruno Desthuilliers <bruno.
42.desthuilli...@wtf.websiteburo.oops.com> wrote:

> The next class in the MRO *is* a superclass of the *instance*. Else it
> wouldn't be in the MRO !-)

Bruno, there is no such a thing as a superclass in a multiple
inheritance
world, and it is a very bad idea to continue to use that terminology.
I was
convinced of that by Bjorn Pettersen in a thread on comp.lang.python
in May 2003
and you may Google for it. You may find there convincing arguments
against the
superclass concept, some of which I report in
http://www.phyast.pitt.edu/~micheles/python/super.html

> Well, I understand that you disagree with both the documention and the
> name of super. As far as I'm concerned, the mere fact that this
> discussion happens is probably a sign that there's something to be fixed
> here - at least wrt documentation, possibly wrt/ naming. But the
> *feature* by itself is certainly something we do want to keep, whatever
> some may argue.

Well, I am personally *against* multiple inheritance (i.e. IMO it
gives more
troubles than advantages)


>
> The goal is to call the correct "next" method according to MRO. Indeed,
> it could have been name "call_next_method".

Right.

Michele Simionato

Hrvoje Niksic

unread,
Sep 19, 2007, 7:16:08 AM9/19/07
to
Michele Simionato <michele....@gmail.com> writes:

> On Sep 19, 12:36 pm, Bruno Desthuilliers <bruno.
> 42.desthuilli...@wtf.websiteburo.oops.com> wrote:
>
>> The next class in the MRO *is* a superclass of the *instance*. Else it
>> wouldn't be in the MRO !-)
>
> Bruno, there is no such a thing as a superclass in a multiple
> inheritance world, and it is a very bad idea to continue to use that
> terminology.

Your arguments against the superclass term seem to assume that there
is only a single superclass to a particular class. In the example you
give in your essay, I would say that all of A, B, and T are
superclasses of C, and Python's super correctly iterates over all of
them.

Wikipedia defines superclass as a "class from which other classes are
derived", which seems perfectly valid for MI.

Michele Simionato

unread,
Sep 19, 2007, 7:36:51 AM9/19/07
to
On Sep 19, 1:16 pm, Hrvoje Niksic <hnik...@xemacs.org> wrote:
> Your arguments against the superclass term seem to assume that there
> is only a single superclass to a particular class.

If you say "the" superclass, then you also assume it is unique. But
the big issue
is that the order of the methods depends on the second argument to
super, the instance,
so there is no useful concept of the superclass of the first argument
of super.
I rest my case.

Michele Simionato

Bruno Desthuilliers

unread,
Sep 19, 2007, 7:55:07 AM9/19/07
to
Michele Simionato a écrit :

> On Sep 19, 12:36 pm, Bruno Desthuilliers <bruno.
> 42.desthuilli...@wtf.websiteburo.oops.com> wrote:
>
>> The next class in the MRO *is* a superclass of the *instance*. Else it
>> wouldn't be in the MRO !-)
>
> Bruno, there is no such a thing as a superclass in a multiple
> inheritance

May I disagree ? Of course, with MI, there's no such thing as "the"
superclass, but there are still superclasses - the classes listed in the
MRO. At least according to a commonly agreed definition of "superclass"...

(snip)

>> Well, I understand that you disagree with both the documention and the
>> name of super. As far as I'm concerned, the mere fact that this
>> discussion happens is probably a sign that there's something to be fixed
>> here - at least wrt documentation, possibly wrt/ naming. But the
>> *feature* by itself is certainly something we do want to keep, whatever
>> some may argue.
>
> Well, I am personally *against* multiple inheritance (i.e. IMO it
> gives more
> troubles than advantages)

Given Python's type system and support for delegation, it's a fact that
MI is not that necessary - FWIW, I don't remember having ever used it
except in Zope2 (where it's commonly a PITA).

Now I don't think there's any reason to remove from MI, since it's
already there, and about as usable as it can be.

Hrvoje Niksic

unread,
Sep 19, 2007, 8:02:55 AM9/19/07
to
Michele Simionato <michele....@gmail.com> writes:

> On Sep 19, 1:16 pm, Hrvoje Niksic <hnik...@xemacs.org> wrote:
>> Your arguments against the superclass term seem to assume that there
>> is only a single superclass to a particular class.
>
> If you say "the" superclass, then you also assume it is unique.

FWIW, Bruno said "a", at least in the section you quoted.

> But the big issue is that the order of the methods depends on the
> second argument to super, the instance, so there is no useful
> concept of the superclass of the first argument of super.

No argument here.

Neil Cerutti

unread,
Sep 19, 2007, 8:58:48 AM9/19/07
to

I can't blame a person for thinking that the call

super(A, self)

is taking the superclass of A. A is perhaps too prominently
placed.

--
Neil Cerutti

Robin Becker

unread,
Sep 19, 2007, 8:44:54 AM9/19/07
to pytho...@python.org
Michele Simionato wrote:
....... interesting stuff ommitted

super seems to return an object of type super, but I cannot seem to find any
documention on this type except for 3.4.2.3

"Super Binding
If a is an instance of super, then the binding super(B, obj).m() searches
obj.__class__.__mro__ for the base class A immediately preceding B and then
invokes the descriptor with the call: A.__dict__['m'].__get__(obj, A). "


--
Robin Becker

Sion Arrowsmith

unread,
Sep 19, 2007, 9:22:22 AM9/19/07
to
Ben Finney <bignose+h...@benfinney.id.au> wrote:
> If a function is named 'super' and operates on
>classes, it's a pretty strong implication that it's about
>superclasses.

But it doesn't (under normal circumstances) operate on classes.
It operates on an *instance*. And what you get back is a (proxy
to) a superclass/ancestor of the *instance*.

(And in the super(A, B) case, you get a superclass/ancestor of
*B*. As has just been said somewhere very near here, what is
misleading is the prominence of A, which isn't really the most
important class involved.)

--
\S -- si...@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
"Frankly I have no feelings towards penguins one way or the other"
-- Arthur C. Clarke
her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump

Michele Simionato

unread,
Sep 19, 2007, 9:41:34 AM9/19/07
to
On Sep 19, 3:22 pm, Sion Arrowsmith <si...@chiark.greenend.org.uk>
wrote:

> Ben Finney <bignose+hates-s...@benfinney.id.au> wrote:
>
> > If a function is named 'super' and operates on
> >classes, it's a pretty strong implication that it's about
> >superclasses.
>
> But it doesn't (under normal circumstances) operate on classes.
> It operates on an *instance*. And what you get back is a (proxy
> to) a superclass/ancestor of the *instance*.
>
> (And in the super(A, B) case, you get a superclass/ancestor of
> *B*. As has just been said somewhere very near here, what is
> misleading is the prominence of A, which isn't really the most
> important class involved.)
>

Happily A (and B too) will become invisible in Python 3000.

Michele Simionato

Neil Cerutti

unread,
Sep 19, 2007, 10:18:20 AM9/19/07
to

Nobody will miss A, but doesn't making B invisible recreate the
current mystery in a new form? We want to get rid of A because it
isn't possible to avoid repeating ourselves. But self is usually
easily available and helps define what's happening.

super.foo()

to me, is even more confusing.

self.super.foo()

or

super(self).foo()

seem like improvements. Unfortunately, neither is one of the
current alternate proposals. The closest competing proposal in
PEP3135 is:

self.__super__.foo()

That syntax seems justified given the specialized application and
involved pitfalls of super that you disclosed in your article.

--
Neil Cerutti
These people haven't seen the last of my face. If I go down, I'm going down
standing up. --Chuck Person

Ed Leafe

unread,
Sep 19, 2007, 2:14:04 PM9/19/07
to pytho...@python.org
On Sep 19, 2007, at 6:52 AM, Michele Simionato wrote:


> Well, I am personally *against* multiple inheritance (i.e. IMO it
> gives more troubles than advantages)

For the sorts of examples that have been used in this thread, it
isn't MI that's problematic; it's the poor quality of the design.

Mixing two complete classes to create a multiply-inherited class is
almost always the sign of poor design. OTOH, mixin-style classes are
a wonderful way to ensure consistency across several different
classes that all need a common behavior added to them. We use mixins
extensively throughout Dabo, and they allow us to give several
classes the desired behaviors, while only having one mixin class to
maintain.

-- Ed Leafe
-- http://leafe.com
-- http://dabodev.com


Scott David Daniels

unread,
Sep 19, 2007, 9:30:53 PM9/19/07
to
Ben Finney wrote:
> al...@mac.com (Alex Martelli) writes:
>
>> In general, "a superclass of foo" means "a class X such that foo is a
>> sublass of X"
>
> Sure. However, this doesn't equate to the assertion that "next class
> in the MRO is the superclass", which is what I was responding to.
>
One thing not pointed out in this thread is that the chain of classes
on the MRO starting with super(A, obj) _will_ include all superclasses
of A. That is the guarantee of the MRO, and that is why super is an
appropriate name.

-Scott David Daniels
Scott....@Acm.Org

Ben Finney

unread,
Sep 19, 2007, 10:00:40 PM9/19/07
to
Hrvoje Niksic <hni...@xemacs.org> writes:

> Ben Finney <bignose+h...@benfinney.id.au> writes:
>
> > Evan is claiming that "the next class in the MRO _is_ a superclass",
> > apparently by his definition or some other that I've not seen.
>
> The definition of superclass is not the issue, the issue is
> "superclass *of which class*"? You expect super(A, self) to iterate
> only over superclasses of A, even when self is an instance of a
> subtype of A.

Yes. Those are the specific parameters to the function call, so that
*is* what I expect.

> What really happens is that super(A, self) yields the next method in
> type(self)'s MRO, which can and does cause include classes that are
> not by any definition superclasses of A.

Then the function is misnamed, and implies that it does the former
("You expect ...") above, instead of the latter ("What really happens
...").

In its latter form, it is worthless to me when I'm looking for "get
superclass of A", but its name and parameters and documentation all
lead me very strongly to believe otherwise.

--
\ "I put contact lenses in my dog's eyes. They had little |
`\ pictures of cats on them. Then I took one out and he ran around |
_o__) in circles." -- Steven Wright |
Ben Finney

Ben Finney

unread,
Sep 19, 2007, 10:04:48 PM9/19/07
to

Yes, it does include those classes. The problem is it also includes an
unknown (to the implementation of A) number of classes that are *not*
superclasses of A. Thus, 'super' is a *bad* name for such a function.

--
\ "There are always those who think they know what is your |
`\ responsibility better than you do." -- Ralph Waldo Emerson |
_o__) |
Ben Finney

Ben Finney

unread,
Sep 19, 2007, 10:08:47 PM9/19/07
to
Scott David Daniels <Scott....@Acm.Org> writes:

Yes, it does include those classes. The problem is it also includes an

Ben Finney

unread,
Sep 19, 2007, 10:12:27 PM9/19/07
to
Scott David Daniels <Scott....@Acm.Org> writes:

Yes, it does include those classes. The problem is it also includes an

Michele Simionato

unread,
Sep 19, 2007, 10:48:13 PM9/19/07
to

I am not against mixins (even if I am certainly very much
against the *abuse* of mixins, such as in Zope 2). What
I would advocate (but I realize that it will never happen
in Python) is single inheritance + mixins a la Ruby.

Michele Simionato

Ben Finney

unread,
Sep 19, 2007, 10:55:35 PM9/19/07
to
Michele Simionato <michele....@gmail.com> writes:

> I am not against mixins (even if I am certainly very much against
> the *abuse* of mixins, such as in Zope 2). What I would advocate
> (but I realize that it will never happen in Python) is single
> inheritance + mixins a la Ruby.

For those unfamiliar with Ruby, could you explain how you see this
being done in Python?

What do you see as an appropriate use of mixin classes, and what an
abuse?

What would the semantics be in Python for "single inheritance + mixins
a la Ruby"? Can you give example syntax?

--
\ "As we enjoy great advantages from the inventions of others, we |
`\ should be glad to serve others by any invention of ours." -- |
_o__) Benjamin Franklin |
Ben Finney

Michele Simionato

unread,
Sep 19, 2007, 11:11:04 PM9/19/07
to
On Sep 20, 4:55 am, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:

> Michele Simionato <michele.simion...@gmail.com> writes:
> > I am not against mixins (even if I am certainly very much against
> > the *abuse* of mixins, such as in Zope 2). What I would advocate
> > (but I realize that it will never happen in Python) is single
> > inheritance + mixins a la Ruby.
>
> For those unfamiliar with Ruby, could you explain how you see this
> being done in Python?

I don't see this being done in Python, it is too late now (for
backward compatibility and all that). But you can still do it
by yourself, the simplest thing being copying the methods
of the mixin class. It is already possible to use a syntax
like this

class MyClass(Base):
mixin(Mixin1, Mixin2, ...)

using P.J. Eby's trick for implementing what he calls class
decorators (see also http://www.phyast.pitt.edu/~micheles/python/classinitializer.html)

But I would not use it, let's use the language we have, not
to invent our own.

> What do you see as an appropriate use of mixin classes, and what an
> abuse?

An example of fine usage of mixin is Tkinter; an example of
bad usage if Zope 2. In any case, I think using composition
in the end is a better solution than mixins (it
is much more scalable).

> What would the semantics be in Python for "single inheritance + mixins
> a la Ruby"? Can you give example syntax?
>

Already done. Since all hierarchies would be flat, super syntax
would be trivial as in Ruby/Java/etc (self.super.meth(args, kw)).

Michele Simionato

Steven D'Aprano

unread,
Sep 19, 2007, 11:13:51 PM9/19/07
to
On Thu, 20 Sep 2007 12:00:40 +1000, Ben Finney wrote:

> In its latter form, it is worthless to me when I'm looking for "get
> superclass of A", but its name and parameters and documentation all lead
> me very strongly to believe otherwise.

Why are you looking for the superclass of A?

If it is specifically for the purpose of inheritance, then surely "which
class(es) is/are the superclass(es)" is an implementation detail that you
shouldn't care about?

In other words, in principle you want to do something like the following:

class MyClass(*base_classes):
def method(self, *args):
print args
return inherit_from_base_classes(self, 'method')(*args)
# could also be written as: self.__inherit__('method', *args)
# or even: self.__inherit__().method(*args)
# or similar.

The details of the inheritance are not important, so long as it calls the
right method of the right base-classes in the right order. You shouldn't
need to know what that order is (except to the extent you've defined the
base classes).

If that's what you want, then you don't need the class itself. You want
*something like* super(), even though the existing implementation of
super is sadly confusing and hard to use.

BUT I think, as far as I can tell, that super() does actually do the
right thing, *if* you can work out just what arguments to give it, and
provided all the base classes *and their bases classes* themselves also
call super().

If you actually want the super-class(es) themselves, heaven knows why,
then you can use MyClass.__base__ and MyClass.__bases__, although you
have to intuit this from communing with the cosmos, because dir(MyClass)
doesn't show them.

--
Steven.

Ben Finney

unread,
Sep 19, 2007, 11:36:41 PM9/19/07
to
Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:

> On Thu, 20 Sep 2007 12:00:40 +1000, Ben Finney wrote:
>
> > In its latter form, it is worthless to me when I'm looking for
> > "get superclass of A", but its name and parameters and
> > documentation all lead me very strongly to believe otherwise.
>
> Why are you looking for the superclass of A?

Currently irrelevant to the point. Whether for good or bad reasons, I
looked for a way to "get the superclass of A". Everything about
'super' — its name, parameter semantics, and documentation — all
firmly led me to believe that was the correct function for that
purpose.

It's not; as currently implemented, it serves an incompatibly
different purpose.

What I'm pointing out is that it's currently very misleadingly named,
its semantics mislead the programmer about how it will be used, and it
is misleadingly documented. Whether it should be removed entirely or
cleaned up, I don't know; all I can do with my current knowledge is to
point out how it gets in the way as it stands.

--
\ "The truth is the most valuable thing we have. Let us economize |
`\ it." -- Mark Twain, _Following the Equator_ |
_o__) |
Ben Finney

Ben Finney

unread,
Sep 19, 2007, 11:41:06 PM9/19/07
to
Michele Simionato <michele....@gmail.com> writes:

> It is already possible to use a syntax like this
>
> class MyClass(Base):
> mixin(Mixin1, Mixin2, ...)
>
> using P.J. Eby's trick for implementing what he calls class
> decorators (see also
> http://www.phyast.pitt.edu/~micheles/python/classinitializer.html)
>
> But I would not use it, let's use the language we have, not
> to invent our own.

Okay. How do we use the language we have to achieve what mixin classes
achieve in Ruby? Can you give an code example that you *would*
recommend for someone looking to do what mixin classes do?

--
\ "In case you haven’t noticed, [the USA] are now almost as |
`\ feared and hated all over the world as the Nazis were." -- |
_o__) Kurt Vonnegut, 2004 |
Ben Finney

Ben Finney

unread,
Sep 19, 2007, 11:41:46 PM9/19/07
to
Michele Simionato <michele....@gmail.com> writes:

> Ben Finney wrote:
> > What do you see as an appropriate use of mixin classes, and what
> > an abuse?
>
> An example of fine usage of mixin is Tkinter; an example of bad
> usage if Zope 2.

Which parts of those two very large code sets do I need to look at to
see the examples you have in mind? I was hoping you could demonstrate
with short code examples.

--
\ "One thing vampire children have to be taught early on is, |
`\ don't run with a wooden stake." -- Jack Handey |
_o__) |
Ben Finney

Steven D'Aprano

unread,
Sep 20, 2007, 12:16:33 AM9/20/07
to
On Thu, 20 Sep 2007 13:36:41 +1000, Ben Finney wrote:

> Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:
>
>> On Thu, 20 Sep 2007 12:00:40 +1000, Ben Finney wrote:
>>
>> > In its latter form, it is worthless to me when I'm looking for "get
>> > superclass of A", but its name and parameters and documentation all
>> > lead me very strongly to believe otherwise.
>>
>> Why are you looking for the superclass of A?
>
> Currently irrelevant to the point. Whether for good or bad reasons, I
> looked for a way to "get the superclass of A".

A.__base__ and A.__bases__ are, I believe, the "right" way to do that.


> Everything about 'super'
> — its name, parameter semantics, and documentation — all firmly led me
> to believe that was the correct function for that purpose.

Name, I can accept.

Parameter semantics? That's borderline. "Get the superclass of A" looks
like it should take ONE and ONLY one argument, namely A. super()
typically takes two arguments, and only in non-typical use does it take a
single argument.

And documentation? From help(super):


class super(object)
| super(type) -> unbound super object
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type, type2) -> bound super object; requires issubclass(type2,
type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
| super(C, self).meth(arg)


Hmmm... it says it returns a super object, not a type or a class and
certainly not "the superclass". It doesn't say what a super object
actually is, but it doesn't say it is a type, or it would say "returns a
type object". Nor does it say it returns the superclass -- it doesn't
even use the term, with or without the hyphen.

And with a typical example shown right there, so close to the top, the
documentation is pretty clear that super() doesn't do what you imagined
it does.

So while I accept that the name of super() is misleading, I don't accept
that the documentation is misleading. Incomplete, yes, hard to
understand, yes, but not misleading.

At least, it didn't mislead _me_, and I'm pretty gullible sometimes...
*wink*

--
Steven.

Michele Simionato

unread,
Sep 20, 2007, 12:30:07 AM9/20/07
to
On Sep 20, 5:41 am, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:

> Okay. How do we use the language we have to achieve what mixin classes
> achieve in Ruby? Can you give an code example that you *would*
> recommend for someone looking to do what mixin classes do?

Since the language we have does have multiple inheritance, let's
use it to implement mixins. My point was that even if Python had
been implemented without multiple inheritance, it would have
been simple to implement mixins, or by copying the methods,
or by dispatching with __getattr__. So, multiple inheritance
is giving us very little for the point of view of mixins; OTOH,
multiple inheritance is giving us a lot of headaches for
what concerns cooperative methods.

Michele Simionato

Michele Simionato

unread,
Sep 20, 2007, 12:40:33 AM9/20/07
to
On Sep 20, 5:41 am, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:

> Michele Simionato <michele.simion...@gmail.com> writes:
> > Ben Finney wrote:
> > > What do you see as an appropriate use of mixin classes, and what
> > > an abuse?
>
> > An example of fine usage of mixin is Tkinter; an example of bad
> > usage if Zope 2.
>
> Which parts of those two very large code sets do I need to look at to
> see the examples you have in mind? I was hoping you could demonstrate
> with short code examples.

Unfortunately you see the issue only when you program in
the large. Take for instance the Plone BaseContent class; I believe
its MRO contains something like 35 classes (I don't remember
the exact number now) in a multiple inheritance hierarchy.
Instances have some something like 400+ methods and attributes.
Now try to understand from which of the parent classes the
attributes came. For Tkinter things are much easier, see
the effbot "Introduction to Tkinter" for a discussion of
the mixin classes it uses. Then try something like
inspect.getmro(Tkinter.Label) , there are only 7 classes
in the hierarchy. Notice that even with single inheritance
you can run in deep hierarchies (Java docet).The problem,
as Guido once said, is the "inheritance is overrated".

Michele Simionato


Ben Finney

unread,
Sep 20, 2007, 12:52:50 AM9/20/07
to
Michele Simionato <michele....@gmail.com> writes:

> Since the language we have does have multiple inheritance, let's
> use it to implement mixins.

> ...


> So, multiple inheritance is giving us very little for the point of
> view of mixins; OTOH, multiple inheritance is giving us a lot of
> headaches for what concerns cooperative methods.

I may be obtuse, but the above statements seem to be professing
contradictory viewpoints.

Do you think multiple inheritance should or should not be used in
Python to do what mixins do?

> My point was that even if Python had been implemented without
> multiple inheritance, it would have been simple to implement mixins,
> or by copying the methods, or by dispatching with __getattr__.

Can you give a code example of how you think mixins should be
implemented in Python, assuming the absence of multiple inheritance?

--
\ "The best way to get information on Usenet is not to ask a |
`\ question, but to post the wrong information." -- Aahz |
_o__) |
Ben Finney

Michele Simionato

unread,
Sep 20, 2007, 1:30:09 AM9/20/07
to
On Sep 20, 6:52 am, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:

> Michele Simionato <michele.simion...@gmail.com> writes:
> > Since the language we have does have multiple inheritance, let's
> > use it to implement mixins.
> > ...
> > So, multiple inheritance is giving us very little for the point of
> > view of mixins; OTOH, multiple inheritance is giving us a lot of
> > headaches for what concerns cooperative methods.
>
> I may be obtuse, but the above statements seem to be professing
> contradictory viewpoints.
>
> Do you think multiple inheritance should or should not be used in
> Python to do what mixins do?

If you want to use mixins in Python, then you should use
multiple inheritance, since multiple inheritance is already
there, no point in reinventing it. OTOH, one may argue that
there are better approaches than mixins, but this is another
topic.

> > My point was that even if Python had been implemented without
> > multiple inheritance, it would have been simple to implement mixins,
> > or by copying the methods, or by dispatching with __getattr__.
>
> Can you give a code example of how you think mixins should be
> implemented in Python, assuming the absence of multiple inheritance?

I have various example somewhere in my hard disk, but now it is time
for me to go to job, so you will have to wait ;) But I
am sure others here can provide examples.

Michele Simionato

thebjorn

unread,
Sep 20, 2007, 1:37:30 AM9/20/07
to
On Sep 19, 3:41 pm, Michele Simionato <michele.simion...@gmail.com>
wrote:

This is great news! Since it is for Py3K it seems clear to me that
super should be a keyword as well (but historically I'm not the best
at channeling Guido ;-)

-- bjorn

thebjorn

unread,
Sep 20, 2007, 2:18:01 AM9/20/07
to
On Sep 20, 6:52 am, Ben Finney <bignose+hates-s...@benfinney.id.au>
wrote:

> Michele Simionato <michele.simion...@gmail.com> writes:
> > Since the language we have does have multiple inheritance, let's
> > use it to implement mixins.
> > ...
> > So, multiple inheritance is giving us very little for the point of
> > view of mixins; OTOH, multiple inheritance is giving us a lot of
> > headaches for what concerns cooperative methods.
>
> I may be obtuse, but the above statements seem to be professing
> contradictory viewpoints.

How so? A language doesn't need MI to have mixins (e.g. Ruby does
this). This doesn't seem to contradict that MI is, in general, a
horrible solution to most problems -- one example being the general
difficulty in groking cooperative (super) methods. A single-
inheritance language, otoh, is also a chore to work with (for a
specific subset of designs) -- unless there is _some_ way to do
mixins. But for the general case I agree with Micele that delegation
is the better solution (Explicit is better than implicit).

> Do you think multiple inheritance should or should not be used in
> Python to do what mixins do?

Michele already answered this, Python has MI so it would just be
confusing to implement mixins any other way.

> > My point was that even if Python had been implemented without
> > multiple inheritance, it would have been simple to implement mixins,
> > or by copying the methods, or by dispatching with __getattr__.
>
> Can you give a code example of how you think mixins should be
> implemented in Python, assuming the absence of multiple inheritance?

Googling for "Ruby mixins tutorial" gave me the following link:
http://www.juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby/

If I tell you that self.something is written @something in Ruby, and
inheritance is written class Base < Parent (as opposed to class
Base(Parent):) everything else should be understandable..?

How to implement include and extend in Python is left as an excercise
for the reader.

-- bjorn


Hrvoje Niksic

unread,
Sep 20, 2007, 4:31:46 AM9/20/07
to
Ben Finney <bignose+h...@benfinney.id.au> writes:

>> The definition of superclass is not the issue, the issue is
>> "superclass *of which class*"? You expect super(A, self) to iterate
>> only over superclasses of A, even when self is an instance of a
>> subtype of A.
>
> Yes. Those are the specific parameters to the function call, so that
> *is* what I expect.

The specific parameters are a type and an instance. Those same
parameters can and do allow for an implementation that accesses
supertypes of type(self). That is in fact more logical; otherwise one
could simply iterate over A.__bases__ and we wouldn't need an
elaborate 'super' construct.

Not iterating only over A's superclasses is the entire *point* of
super. The only deficiency of super I see in this thread is
incomplete documentation.

Steven D'Aprano

unread,
Sep 20, 2007, 5:25:04 AM9/20/07
to
On Thu, 20 Sep 2007 14:52:50 +1000, Ben Finney wrote:

> Can you give a code example of how you think mixins should be
> implemented in Python, assuming the absence of multiple inheritance?

I'll take a shot at it... use automatic delegation to the mixin class.

class Parrot(object):
def fly(self):
return "The parrot can fly short distances."
def talk(self):
return "I'm pining for the fjords."

class Albatross(object):
def fly(self):
return "The albatross is known to fly enormous distances."


# Now I want a talking Albatross, without using multiple inheritance.

class TalkingAlbatross(Albatross):
def __init__(self, *args, **kwargs):
# avoid triggering __setargs__
self.__dict__['mixin'] = Parrot()
# avoid using super() so Ben doesn't get cranky
self.__class__.__base__.__init__(self, *args, **kwargs)
def __getattr__(self, name):
return getattr(self.mixin, name)
def __hasattr__(self, name):
return hasattr(self.mixin, name)
def __delattr__(self, name):
return delattr(self.mixin, name)
def __setattr__(self, name, value):
return setattr(self.mixin, name, value)


Am I close?


--
Steven.

Marshall T. Vandegrift

unread,
Sep 20, 2007, 10:31:41 AM9/20/07
to pytho...@python.org
Michele Simionato <michele....@gmail.com> writes:

> I am not against mixins (even if I am certainly very much against the
> *abuse* of mixins, such as in Zope 2). What I would advocate (but I
> realize that it will never happen in Python) is single inheritance +
> mixins a la Ruby.

Ruby might be a bad example here. Although the Ruby language syntax
only supports single inheritance, mixins are implemented as multiple
inheritance under the hood. That is, inheriting from a class and
including a class as a mixin modifies the sub-/mixing class in exactly
the same way.

-Marshall

Michele Simionato

unread,
Sep 20, 2007, 11:36:31 AM9/20/07
to
On Sep 20, 4:31 pm, "Marshall T. Vandegrift" <llas...@gmail.com>
wrote:

The difference is that there is no cooperation, so you don't need to
bang your
head in order to understand the method resolution order.

Michele Simionato

OKB (not okblacke)

unread,
Sep 20, 2007, 12:56:55 PM9/20/07
to
Steven D'Aprano wrote:

> class super(object)
> | super(type) -> unbound super object
> | super(type, obj) -> bound super object; requires isinstance(obj,
> | type) super(type, type2) -> bound super object; requires
> | issubclass(type2, type) Typical use to call a cooperative
> | superclass method: class C(B):
> | def meth(self, arg): super(C, self).meth(arg)

. . . but from the documentation on the website:

super(type[, object-or-type])
Return the superclass of type.

I do think this should be changed, since it really isn't true. It
should probably say something like "return the next element after "type"
in the MRO of "element-or-type".

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown

0 new messages