[General lang] how to call a parent
Jeff Epler
jepler at unpythonic.net
Sun Jun 15 22:19:55 EDT 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