473,385 Members | 1,546 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

What are super()'s semantics?

I'm reading Alex Martelli's "Nutshell" second edition. In the section
called "Cooperative superclass method calling", he presents a diamond
inheritance hierachy:

class A(object):
def met(self):
print "A.met"
class B(A):
def met(self):
print "B.met"
A.met(self)
class C(A):
def met(self):
print "C.met"
A.met(self)
class D(B,C):
def met(self):
print "D.met"
B.met(self)
C.met(self)
D().met() # essentially "D B A C A"

Martelli says "In this code, when we call D().met(), A.met ends up being
called twice. How can we ensure that each ancestor's implementation of
the method is called once, and only once? The solution is to use
built-in type super. super(aclass, obj), which returns a special
superobject of object obj. When we look up an attribute (e.g., a method)
in this superobject, the lookup begins after class aclass in obj's
MRO. We can therefore rewrite the previous code as:

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

class B(A):
def met(self):
print "B.met"
super(B, self).met()

class C(A):
def met(self):
print "C.met"
super(C, self).met()

class D(B,C):
def met(self):
print "D.met"
super(D, self).met()

D().met() # essentially "D B C A"
Now, D().met() results in exactly one call to each class's version of
met."

I see that this is true, but I am confused by the explanation (the bit
about truncated lookup in the class's MRO). In particular:

1. The super() call in D somehow invokes both parent class methods
instead of stopping when the method is resolved in B. This has
nothing to do with truncated lookup per se. Why isn't the output "D
B A"?

2. If I understand correctly, B's MRO is (B, A) and super(B, self) would
have an MRO of (A). Similarly for C. So it seems that by the above
explanation, A.met() would still be invoked twice (assuming both
B.met() and C.met() are invoked).

I guess I can just take it on faith that super() invokes everything once
and only once, but I'd rather understand how. Can someone point me to a
more complete description of super()'s semantics and how they work?

BTW, the official docs are even worse in this regard. AFAICT, they
essentially say that super() returns a superclass with no discussion of
diamond inheritance or any hint of how the semantics of super(B,
self).met() would be any different than those of A.met(self).

This seems like very important functionality to be documented in the
official docs so poorly.

Mike
Sep 4 '06 #1
9 2176
Mike Krell wrote:
BTW, the official docs are even worse in this regard. AFAICT, they
essentially say that super() returns a superclass with no discussion of
diamond inheritance or any hint of how the semantics of super(B,
self).met() would be any different than those of A.met(self).

This seems like very important functionality to be documented in the
official docs so poorly.
Well, you are right. I remember being fooled myself. 'super' does NOT
return a
superclass. Actually, there is no meaningful concept of superclass in a
multiple inheritance
world. Anyway, the MRO concept is documented here:

http://www.python.org/download/releases/2.3/mro/

(yes, it is not easy to find this link in python.org).

Michele Simionato

Sep 4 '06 #2
Mike Krell wrote:
class A(object):
def met(self):
print "A.met"

class B(A):
def met(self):
print "B.met"
super(B, self).met()

class C(A):
def met(self):
print "C.met"
super(C, self).met()

class D(B,C):
def met(self):
print "D.met"
super(D, self).met()

D().met() # essentially "D B C A"
[snip]
2. If I understand correctly, B's MRO is (B, A) and super(B, self) would
have an MRO of (A).
This is the source of your misunderstanding.

Essentially, it's objects that have MROs, not classes. When you create
an object of class D, the MRO of that object is (D,B,C,A), and it
doesn't change, even when you're executing code defined in class B.
Thus, when self is of type D, super(B,self) does not have and MRO of
(A,), but (C,A). Therefore, super(B,self).__init__() invokes
C.__init__.
Carl Banks

Sep 4 '06 #3
Le lundi 04 septembre 2006 12:25, Mike Krell a écrit*:
1. The super() call in D somehow invokes both parent class methods
* *instead of stopping when the method is resolved in B. This has
* *nothing to do with truncated lookup per se. *Why isn't the output "D
* *B A"?
Yes but, super(B, B()) and super(B,D()) are not the same object like the code
below shows.
2. If I understand correctly, B's MRO is (B, A) and super(B, self) would
* *have an MRO of (A). *Similarly for C. *So it seems that by theabove
* *explanation, A.met() would still be invoked twice (assuming both
* *B.met() and C.met() are invoked).
super(class_, self), is an instance of super, so its class, "super", have a
mro of [<type 'super'>, <type 'object'>]....
"self" in each method call is the same and indeed its type's mro doesn't
change !
-- In [80]: class A(object) :
....: def sup(self) :
....: print 'A'
....:
....:

In [81]: class B(A) :
....: def sup(self) :
....: print 'B'
....: s(B, self).sup()
....:
....:

In [82]: class C(A) :
....: def sup(self) :
....: print 'C'
....: s(C, self).sup()
....:
....:

In [83]: class D(B,C) :
....: def sup(self) :
....: print 'D'
....: s(D, self).sup()
....:
....:

In [97]: class s(super) :
....: def __new__(*a) :
....: print a
....: return super.__new__(*a)
....:
....:

In [98]: D().sup()
D
(<class '__main__.s'>, <class '__main__.D'>, <__main__.D object at
0xa763186c>)
B
(<class '__main__.s'>, <class '__main__.B'>, <__main__.D object at
0xa763186c>) <--- instance is always the same !!
C
(<class '__main__.s'>, <class '__main__.C'>, <__main__.D object at
0xa763186c>) <--- instance is always the same !!
A

In [100]: super(B, D()).sup()
C
(<class '__main__.s'>, <class '__main__.C'>, <__main__.D object at
0xa763178c>)
A

This shows that C is called following the mro of type(D()) from class B to top
and not the mro of B.

All the magic is in the __getattribute__ of super which retrieve the
following class in the mro given its argument.
In [140]: class A(object) :
.....: def sup(self) : print 'a'
.....:
.....:

In [141]: class B(A) :
.....: def sup(self) : print 'b'
.....:
.....:

In [142]: class C(A) :
.....: def sup(self) : print 'c'
.....:
.....:

In [143]: class D(B,C) : pass
.....:
In [147]: super.__getattribute__(super(D,D()), 'sup')()
b

In [148]: super.__getattribute__(super(B,D()), 'sup')()
c

In [149]: super.__getattribute__(super(C,D()), 'sup')()
a

Hope this is clear.

_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Sep 4 '06 #4
Le lundi 04 septembre 2006 13:48, Carl Banks a écrit*:
Essentially, it's objects that have MROs, not classes.
Wrong, __mro__ is an attribute of types (subtypes of type) but like __class__
it is not available in the instances.
mro() is standard a method of type.

In [150]: A.mro()
Out[150]: [<class '__main__.A'>, <type 'object'>]

In [152]: A().mro()
---------------------------------------------------------------------------
exceptions.AttributeError Traceback (most recent
call last)

/home/maric/<ipython console>

AttributeError: 'A' object has no attribute 'mro'

In [154]: type.mro(A)
Out[154]: [<class '__main__.A'>, <type 'object'>]
--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Sep 4 '06 #5

Maric Michaud wrote:
Le lundi 04 septembre 2006 13:48, Carl Banks a écrit :
Essentially, it's objects that have MROs, not classes.
Wrong, __mro__ is an attribute of types (subtypes of type) but like __class__
it is not available in the instances.
mro() is standard a method of type.
I agree that was misleading; I should have said something like, "Type
of an object never changes, therefore the MRO used for an object is
fixed."

BTW, __class__ is available to instances. (Were you thinking of
__bases__?)
Carl Banks

Sep 4 '06 #6
Le lundi 04 septembre 2006 22:29, Carl Banks a écrit*:
BTW, __class__ is available to instances. *(Were you thinking of
__bases__?)
hmmm, I guess they're not the same, are they ?

but you're right, __bases__ and some others are class attributes not available
in instances, I wonder where is this documented and I'm not enough familiar
with python' source code to find this.

Also this create weird things, like a code posted on this list, which was
very confusing and looked to something like :

In [24]: class A(object) :
....: __class__ = list
....:
....:

In [25]: A.__class__
Out[25]: <type 'type'>

In [26]: A().__class__
Out[26]: <type 'list'>

In [27]: isinstance(A(), list) # ouch !
Out[27]: True

In [29]: type(A())
Out[29]: <class '__main__.A'>

In [30]: type(A()).mro()
Out[30]: [<class '__main__.A'>, <type 'object'>]
--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Sep 4 '06 #7
Maric Michaud <ma***@aristote.infowrote in
news:ma****************************************@py thon.org:
[examples snipped]

Hope this is clear.
Yes, I get it now. In a prior section in "Nutshell", Alex M. goes over the
MRO as well as the __mro__ attribute. I remembered the fact that the
__mro__ attribute can be referenced only on classes. Somehow, this
confused me into thinking that the operative MRO for each call to super()
would be dictated by the class where the call was being made rather than by
the single instance of D as specified by the second parameter.

Mike
Sep 5 '06 #8
"Michele Simionato" <mi***************@gmail.comwrote in
news:11**********************@i42g2000cwa.googlegr oups.com:
Anyway, the MRO concept is documented here:

http://www.python.org/download/releases/2.3/mro/
A very edifying document. Indeed, in "Nutshell" Alex M. mentions your
paper at the end of his high-level explanation of the MRO. In my infinite
wisdom, I had chosen not to follow up by reading about the nitty-gritty
details :-)

As I mentioned in another post, it wasn't my lack of understanding of the
MRO per se that tripped me up. I somehow managed to know that in Alex's
example, an instance of the D class would have an MRO of essentially (D, C,
B, A), and yet not realize that this was strangly similar to the output of
the example. D'oh!

Thanks,
Mike

Sep 5 '06 #9
Maric Michaud wrote:
Le lundi 04 septembre 2006 22:29, Carl Banks a écrit :
>>BTW, __class__ is available to instances. (Were you thinking of
__bases__?)


hmmm, I guess they're not the same, are they ?

but you're right, __bases__ and some others are class attributes not available
in instances, I wonder where is this documented and I'm not enough familiar
with python' source code to find this.

Also this create weird things, like a code posted on this list, which was
very confusing and looked to something like :

In [24]: class A(object) :
....: __class__ = list
....:
....:

In [25]: A.__class__
Out[25]: <type 'type'>

In [26]: A().__class__
Out[26]: <type 'list'>

In [27]: isinstance(A(), list) # ouch !
Out[27]: True

In [29]: type(A())
Out[29]: <class '__main__.A'>

In [30]: type(A()).mro()
Out[30]: [<class '__main__.A'>, <type 'object'>]

You are beginning to appreciate the meaning of the phrase "Python is a
language for use by consenting adults". The general philosophy is to
provide a coherent and easily-used framework in the expectation that
users will not shoot themselves in the foot (too often).

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Sep 5 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Kerim Borchaev | last post by:
Hello! Always when I use "super" I create a code duplication because class used as first arg to "super" is always the class where the method containing "super" was defined in: ''' class C:...
7
by: Michele Simionato | last post by:
So far, I have not installed Prothon, nor I have experience with Io, Self or other prototype-based languages. Still, from the discussion on the mailing list, I have got the strong impression that...
0
by: Michele Simionato | last post by:
Here is an idea for a nicer syntax in cooperative method calls, which is not based on Guido's "autosuper" example. This is just a hack, waiting for a nicer "super" built-in ... Here is example...
0
by: Delaney, Timothy C (Timothy) | last post by:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286195 This is a new version of super that automatically determines which method needs to be called based on the existing stack frames....
10
by: Chris Green | last post by:
Good day, I've done a bit of searching in the language reference and a couple pages referring the behavior of super() but I can't find any discussion of why super needs the name of the class as...
6
by: Steven Bethard | last post by:
When would you call super with only one argument? The only examples I can find of doing this are in the test suite for super. Playing around with it: py> class A(object): .... x = 'a'...
9
by: Paul Rubin | last post by:
I'm trying the super() function as described in Python Cookbook, 1st ed, p. 172 (Recipe 5.4). class A(object): def f(self): print 'A' class B(object): def f(self):
5
by: Erwan Adam | last post by:
Hi all, I have a problem with the use of descriptors and super. The file is : # --------------- class Desc(object): def __init__(self, class_name): self.class_name = class_name
18
by: Xah Lee | last post by:
What are OOP's Jargons and Complexities Xah Lee, 20050128 Classes, Methods, Objects In computer languages, often a function definition looks like this: subroutine f (x1, x2, ...) {...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.