Perhaps this should have been posted on a Python board, but I only care about how this applies to wxPython classes.
General explanations and definitions of the Python super method have fallen far short for me, so I was wondering why it would wanted to be used in a class definition. That is, what are its advantages and hazards ? (I’ve seen lots of posts about its hazards, but I can’t decipher what they mean because I can’t figure out what super does in the first place!)
Did you see this thread from a couple weeks ago?
http://groups.google.com/group/wxpython-users/browse_thread/thread/f9860b459f4dbc5b?hl=en#
···
On Thu, Mar 3, 2011 at 11:16 AM, Ray Pasco pascor22234@gmail.com wrote:
Perhaps this should have been posted on a Python board, but I only care about how this applies to wxPython classes.
General explanations and definitions of the Python super method have fallen far short for me, so I was wondering why it would wanted to be used in a class definition. That is, what are its advantages and hazards ? (I’ve seen lots of posts about its hazards, but I can’t decipher what they mean because I can’t figure out what super does in the first place!)
–
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en
Yes, that’s why I’m asking in the first place! That thread assumes the reader already has a basic understanding of super(). I do not. What does super() do ?
···
On Mar 3, 2:38 pm, mw m...@tangsoo.us wrote:
Did you see this thread from a couple weeks ago?http://groups.google.com/group/wxpython-users/browse_thread/thread/f9.…
Ray Pasco wrote:
> Did you see this thread from a couple weeks ago?[http://groups.google.com/group/wxpython-users/browse_thread/thread/f9.](http://groups.google.com/group/wxpython-users/browse_thread/thread/f9.).. Yes, *that's why I'm asking in the first place!* That thread
assumes the reader already has a basic understanding of super(). I
do not. What does super() do ?
It is a "shortcut" to allow you to access the base class of a
derived class, without having to know or type the base class name.
For example:
` class This_is_a_very_long_class_name(object):
def __init__(self):
pass
class Derived(This_is_a_very_long_class_name):
def __init__(self):
super(Derived,self).__init__() #1
This_is_a_very_long_class_name.__init__(self) #2`
Those last two lines are two ways of spelling the same thing.
Besides just the spelling, this also allows you to change the base
class without having to go through all of your code and replace the
base class name. C++ programmers often do this with a typedef in
their derived classes.
There is another more obscure use for super as well, but you're
unlikely to come across it for a while yet.
Which obscure use is that? Please tell us. This was very informal for other newbies as well. So do tell more.
Thanks! So, it's a way of deriving my own class by way of another
derived class ?
Do I understand correctly that in your example both the original class
and the newly derived class need to be initialized ?
What are the advantages to calling super() and doing this ? With class
inheritance I already have control over initialization of the base
class. I must be missing something else.
···
On Mar 4, 8:12 pm, Tim Roberts <t...@probo.com> wrote:
It is a "shortcut" to allow you to access the base class of a derived
class, without having to know or type the base class name. For example:class This\_is\_a\_very\_long\_class\_name\(object\): def \_\_init\_\_\(self\): pass class Derived\(This\_is\_a\_very\_long\_class\_name\): def \_\_init\_\_\(self\): super\(Derived,self\)\.\_\_init\_\_\(\) \#1 This\_is\_a\_very\_long\_class\_name\.\_\_init\_\_\(self\) \#2
Those last two lines are two ways of spelling the same thing. Besides
just the spelling, this also allows you to change the base class without
having to go through all of your code and replace the base class name.
C++ programmers often do this with a typedef in their derived classes.
--
Tim Roberts, t...@probo.com
Providenza & Boekelheide, Inc.
I expect that Tim was thinking of the ability to delegate to a sibling class in multiple inheritance situations.
···
On 3/5/11 2:23 AM, Bo�tjan Mejak wrote:
Which obscure use is that? Please tell us. This was very informal for
other newbies as well. So do tell more.
--
Robin Dunn
Software Craftsman
It's so you can get to the parent (or sibling) class without knowing the name of that class.
···
On 3/5/11 8:40 AM, Ray Pasco wrote:
What are the advantages to calling super() and doing this ? With class
inheritance I already have control over initialization of the base
class. I must be missing something else.
--
Robin Dunn
Software Craftsman
Try running this:
class A(object):
def foo(self):
print 'A'
class B(A):
def foo(self):
print 'B'
super(B, self).foo()
class C(A):
def foo(self):
print 'C'
super(C, self).foo()
class D(B,C):
def foo(self):
print 'D'
super(D, self).foo()
d = D()
d.foo()
Notice that A is printed only once even though it is derived from twice in the class hierarchy, and also that B does not have to know that it should delegate to C before A because C is the next class in the MRO of D.
···
On 3/5/11 8:45 AM, Robin Dunn wrote:
On 3/5/11 8:40 AM, Ray Pasco wrote:
What are the advantages to calling super() and doing this ? With class
inheritance I already have control over initialization of the base
class. I must be missing something else.It's so you can get to the parent (or sibling) class without knowing the
name of that class.
--
Robin Dunn
Software Craftsman
Try running this:
…
Notice that A is printed only once even though it is derived from twice in the class hierarchy, and also that B does not have to know that it should delegate to C before A because C is the next class in the MRO of D.
Robin Dunn
Software Craftsman
Your code explains most of what I wanted to know. The attached code is just an expansion of the original code. When run, it outputs:
a.foo()
A_BaseClass.foo()
b.foo()
B_BaseClass.foo()
c.foo()
C_DerivedClass.foo()
A_BaseClass.foo()
d.foo()
D_DerivedClass.foo()
B_BaseClass.foo()
e.foo()
E_DoubleyDerivedClass.foo()
A_BaseClass.foo()
f.foo()
E_DoubleyDerivedClass.foo()
A_BaseClass.foo()
When e.foo() and f.foo() is called, why isn’t B_BaseClass().foo called ?
Meaning, how do I initialize the rest of the base classes after the first one listed in the derivation class list ?
Super_Demo.py (1.33 KB)
Bo�tjan Mejak wrote:
Which obscure use is that? Please tell us. This was very informal
for other newbies as well. So do tell more.
Python allows multiple inheritance.� Although not terribly common,
it is possible to construct complicated inheritance trees, including
a “diamond” pattern, in which several of your base classes derive
from some common ancestor.� If you just use the normal method of
calling a base class, like the following, you end up calling the D
constructor twice, once from B, once from C:
class D(object):
`��� def __init__(self):` `������� print "In D.__init__"` `������� object.__init__(self)` `class B(D):` `��� def __init__(self):` `������� print "In B.__init__"` `������� D.__init__(self)` `class C(D):` `��� def __init__(self):` `������� print "In C.__init__"` `������� D.__init__(self)` `class A(B,C):` `��� def __init__(self):` `������� print "In A.__init__"` `������� B.__init__(self)` ` ������� C.__init__(self)` `A()`
But if you religiously use "super" instead, it handles this case
correctly, and the “D” constructor will only be called once:
Ray Pasco wrote:
It is a "shortcut" to allow you to access the base class of a derived
class, without having to know or type the base class name. For example:class This_is_a_very_long_class_name(object):
def __init__(self):
passclass Derived(This_is_a_very_long_class_name):
def __init__(self):
super(Derived,self).__init__() #1
This_is_a_very_long_class_name.__init__(self) #2Those last two lines are two ways of spelling the same thing. Besides
just the spelling, this also allows you to change the base class without
having to go through all of your code and replace the base class name.
C++ programmers often do this with a typedef in their derived classes.
--
Tim Roberts, t...@probo.com
Providenza & Boekelheide, Inc.Thanks! So, it's a way of deriving my own class by way of another
derived class ?
Well, you have always been able to derive classes from other classes.
That's a big feature of Python.
Do I understand correctly that in your example both the original class
and the newly derived class need to be initialized ?
Yes, although __init__ is just one example. It's easy to use as an
example, because it's easy to demo, but you can use any function there.
Technically, the "super" function returns a proxy object of the type
that would have been created had your class not been there. There is a
clear rule (in Python) for determining the next base class, and "super"
returns an object of the next class in that list.
What are the advantages to calling super() and doing this ? With class
inheritance I already have control over initialization of the base
class. I must be missing something else.
Because sometimes you don't know -- and don't need to know -- the
ancestry of the classes you derive from. If you look at my other
example, I have an class A that derives from B and C. I can certainly
call B's and C's constructor explicitly, but if both of those classes
derive from a common class D (perhaps through several intermediate
classes), then I have a problem. The explicit calls will end up calling
D's constructor twice. The super() function solves that problem.
You can still have control over the ordering. The ordering rules in
Python are clearly stated (although not commonly known). You control
the ordering of the base class calls by tweaking the ordering in your class:
class A( B, C ):
Now, honestly, I don't know whether B or C is first in the list, because
it hasn't been important for me, but the rule is explicit, and it's in
the Python documentation.
···
On Mar 4, 8:12 pm, Tim Roberts <t...@probo.com> wrote:
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
Try running this:
...Notice that A is printed only once even though it is derived from
twice in the class hierarchy, and also that B does not have to know
that it should delegate to C before A because C is the next class in
the MRO of D.
--
Robin Dunn
Software Craftsman
http://wxPython.orgYour code explains most of what I wanted to know. The attached code is
just an expansion of the original code. When run, it outputs:When e.foo() and f.foo() is called, why isn't B_BaseClass().foo called ?
Because your A and B classes do not participate in the MRO. In other words, they break the chain because they do not use super() themselves.
Meaning, how do I initialize the rest of the base classes after the
first one listed in the derivation class list ?
class A_BaseClass( object ) :
def foo( self ) :
print 'A_BaseClass.foo()'
if hasattr(super( A_BaseClass, self ), 'foo'):
super( A_BaseClass, self ).foo()
···
On 3/6/11 10:33 AM, Ray Pasco wrote:
--
Robin Dunn
Software Craftsman
> Meaning, how do I initialize the rest of the base classes after the
> first one listed in the derivation class list ?
class A_BaseClass( object ) :
def foo( self ) :
print 'A_BaseClass.foo()'
if hasattr(super( A_BaseClass, self ), 'foo'):
super( A_BaseClass, self ).foo()--
Robin Dunn
Software Craftsmanhttp://wxPython.org
Thanks, Tim and Robin. I'm going to have to take some so I can wrap
my brain around all this.