Credit: Alex Martelli
You need
functionality equivalent to Java’s
super
keyword to delegate part
of a method to a superclass.
When you override the method of a
superclass, you often want to call the superclass’s
version of a method as part of your override. In a Python 2.2
new-style class, the new built-in
super
function helps a lot:
class A(B, C): def amethod(self): # First, call the superclass's version super(A, self).amethod( ) # Continue with A-specific implementation ...
With super
, you transparently call
amethod
in the B
or
C
superclass, or in both, if both classes define
it, and B
also uses super
in
the same way.
This doesn’t work for classic classes (or in Python 2.1 and earlier), but we can arrange for a slightly weaker version:
def super(class_, inst): # First, try the real thing, if available and applicable try: return _ _builtins_ _.super(class_, inst) except (TypeError, AttributeError): pass # Otherwise, arrange for a weaker substitute class Super: def _ _init_ _(self, class_, inst): # Just remember the bases and instance self.bases = class_._ _bases_ _ self.inst = inst def _ _getattr_ _(self, name): # Seek the bases for an unbound method; break when found for base in self.bases: method = getattr(name, method, None) if method is not None: break else: raise AttributeError, name # No base has it, so raise # Found, so create and return the bound-method version import new return new.instancemethod(method, self.inst, method.im_class)
Used in a classic class, this super
calls a method
only in the base where it first finds it. In classic-class settings,
to call a method in all superclasses that have it, use the approaches
shown in Recipe 5.4.
When you override a method, it is quite common to want to delegate
part of its execution to a superclass. In other words, even though
you are overriding the method to provide extra features, you still
need to use the superclass’s implementation as part
of your own. If there is just a single superclass, or if you know
which superclass implementation you need to call, it is easy to do
this with the normal Python idiom Superclass.themethod(self, ...)
. However, with multiple inheritance, you may not know
which superclass you want. If you refactor your code, you may move
methods between superclasses, so you shouldn’t
depend on a method’s exact location in the subclass
you’re writing. Often, you may want to call all
implementations of a method in all superclasses, particularly for
special methods, such as _ _init_ _
or _ _del_ _
.
Python 2.2’s new-style object model offers a direct
solution for this task: the new super
built-in
function. You call super
with two arguments: the
class in which you’re overriding the method and
self
. Looking up any method on
super
’s return value returns the
appropriate superclass implementation to call as a bound method
(i.e., you don’t explicitly pass it
self
again). If you use this technique
systematically in all the classes that override this method, you end
up calling every superclass implementation (in the new-style
model’s canonical method resolution order, so you
don’t have to worry about diamond-shaped inheritance
graphs).
In the classic object model, super
doesn’t work (and in Python 2.1 and earlier, it
doesn’t even exist). In this recipe, we simulate it
in a slightly weaker but still useful way. The recipe defines a
factory function (i.e., a function
that builds and returns a suitable object) also called
super
, so that it shadows the built-in
super
from normal use. You use it as you use the
built-in super
, except that you can use it in
classic or new-style classes interchangeably. The
recipe’s function first tries to use the built-in
super
. If that’s not found or not
applicable, the function falls back to the slightly weaker but useful
equivalent, the Super
class.
The Super
class does not let you transparently call
a method in several superclasses, nor does it apply the new-style
method resolution order. However, it does work for simple cases.
_ _init_ _
simply stashes away the instance and
the list of bases. _ _getattr_ _
loops on all
bases; if the loop does not find the method, and thus never
break
s, the else
clause is
entered, which raises AttributeError
. If the
method is found, _ _getattr_ _
wraps it into a
bound method (the better to simulate the built-in
super
’s workings) and returns it.
The wrapping is performed via the instancemethod
function in the new
module using the
im_class
attribute of the unbound method, which
records the class that supplied the method.
Recipe 5.4, Recipe 14.8, and Recipe 14.9.