[General lang] how to call a parent

Jeff Epler jepler at unpythonic.net
Mon Jun 16 04:19:55 CEST 2003


On Sun, Jun 15, 2003 at 11:01:46PM +0000, John Fabiani wrote:
> I'm just starting to use python and playing with the tools and the language. 
> After building a few small windows (via BOA) I realized that I did not know
> how to create a class that allowed reuse in a general way.  I was testing
> how classes are used.  I was able create properties, call the __init__ of
> the parent class .etc  But then I realized I did not have a way to call a
> parent of control - such as a container.  Also I was not aware of "super". 
> I'm guessing that will help.  Still learning!!!!!!!!!!!!
> John

Yeah.  I didn't get in your first message that you were asking about the
inheritance tree -- I thought you were talking about parents in terms of a
tree-representation of an HTML document, for instance.

You must use super() if you expect the inheritance graph to be a DAG instead
of a tree (i.e., there's a "diamond shape" hiding somewhere).  For
instance, if you have
               A
              / \
             /   \
            B     C
             \   /
              \ /
               D
	class A(object): pass # super works only for "new-style objects"
	class B(A): pass
	class C(A): pass
	class D(B,C): pass
then follwing the rule (for cooperative methods) "each subclass method calls
the method defined on each of its base classes" will get you into trouble:
D.f calls both B and C, which in turn gives *two* calls to A.f (not the one
call you'd expect).  Super defines a strange-seeming order where each subclass
method calls *one* method defined on a base class, but the call may not be
to an ancestor class of the class making the call via super.  Confused yet?

Now, if you don't want to accomodate diamond-shape inheritance, then
there's a simpler way.  Just call the method by referencing the class
attribute, and explicitly name self as the first argument:
>>> class A:
...     def f(self, arg): print "A.f(%r,%r)" % (self, arg)
... 
>>> class B(A):
...	def f(self, arg):
...         print "B.f(%r,%r)" % (self, arg)
...         A.f(self, "spam") # call parent method
...
>>> o = B()
>>> o.f(37)
B.f(<__main__.B instance at 0x81d548c>,37)
A.f(<__main__.B instance at 0x81d548c>,'spam')

Wondering about the diamond and super?  Write the code yourself.  The
cooperative call looks like this:
        super(X, self).f(arg)
where X is the name of the class in which you're defining the method.
Remember, super only works when you make your classes new-style by deriving
from object.

Jeff





More information about the Python-list mailing list