473,796 Members | 2,661 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

What are super()'s semantics?

I'm reading Alex Martelli's "Nutshell" second edition. In the section
called "Cooperativ e 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 2204
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 misunderstandin g.

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.__getattr ibute__(super(D ,D()), 'sup')()
b

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

In [149]: super.__getattr ibute__(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.Attr ibuteError 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******** *************** *************** **@python.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.comwr ote in
news:11******** **************@ i42g2000cwa.goo glegroups.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
2333
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: def method(self): super(C, self).method() '''
7
3564
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 you do not actually need to fork Python in order to implement prototypes. It seems to me that Python metaclasses + descriptors are more than powerful enough to implementing prototypes in pure Python. I wrote a module that implements part of what...
0
1241
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 of usage: from cooperative import Cooperative class B(Cooperative): def print_(self):
0
1515
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. It's much nicer for writing cooperative classes. It does have more overhead, but at this stage I'm not so concerned about that - the important thing is it actually works. Note that this uses sys._getframe() magic ...
10
2137
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 an argument. Feel free to point me into the bowels of google if this has been discussed to death already. super(self).method() seems like super could just do the right thing...
6
2016
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' .... py> class B(A): .... x = 'b' ....
9
1715
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
1439
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
1840
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, ...) { variables ...
0
9530
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10459
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10236
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9055
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7552
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6793
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5445
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5577
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4120
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

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.