What are super()'s semantics?

Maric Michaud maric at aristote.info
Mon Sep 4 07:53:23 EDT 2006


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 the above
>    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



More information about the Python-list mailing list