super() doesn't get superclass

H

Hrvoje Niksic

Michele Simionato said:
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.
 
M

Michele Simionato

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
 
B

Bruno Desthuilliers

Michele Simionato a écrit :
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 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.
 
H

Hrvoje Niksic

Michele Simionato said:
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.
 
R

Robin Becker

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). "
 
N

Neil Cerutti

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


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.

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.
 
S

Sion Arrowsmith

Ben Finney said:
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.)
 
M

Michele Simionato

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
 
N

Neil Cerutti

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

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.
 
E

Ed Leafe

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
 
S

Scott David Daniels

Ben said:
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
(e-mail address removed)
 
B

Ben Finney

Hrvoje Niksic said:
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.
 
B

Ben Finney

Scott David Daniels said:
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.

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.
 
B

Ben Finney

Scott David Daniels said:
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.

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.
 
B

Ben Finney

Scott David Daniels said:
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.

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.
 
M

Michele Simionato

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.

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
 
B

Ben Finney

Michele Simionato said:
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?
 
M

Michele Simionato

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
 
S

Steven D'Aprano

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.
 
B

Ben Finney

Steven D'Aprano said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,732
Latest member
ArronPalin

Latest Threads

Top