Welcome, guest | Sign In | My Account | Store | Cart

Python has no equivalent to Java's "super" keyword (so that some part of a method can be delegated to the superclass), but it's easy to get similar convenience despite Python's multiple-inheritance generality.

Python, 33 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class CallbaseError(AttributeError):
    pass

def callbase(obj, base, methodname='__init__', args=(), raiseIfMissing=None):
    try: method = getattr(base, methodname)
    except AttributeError: 
        if raiseIfMissing:
            raise CallbaseError, methodname
        return None
    if args is None: args = ()
    return method(obj, *args)

# an example: ensure __init__ is called w/o args on _all_ bases
# (if present; ignore no-such-method issues)
class A(B, C, D, E):
    def __init__(self):
        for base in A.__bases__:
            callbase(self, base)
        # class-A-specific initialization here
        self.cachePlokki = {}
# another typical use case: override a method in some base,
# also providing some other stuff around it; e.g. for cache
# on-demand purposes
    def getPlokki(self, *args):
        try: return self.cachePlokki[args]
        except IndexError: pass
        for base in self.__class__.__bases__:
            try: result=callbase(self, base, 'getPlokki', args, 1)
            except CallbaseError: pass
            else: break
        # ok to raise here if result still not bound
        self.cachePlokki[args] = result
        return result

A frequent need when using inheritance is to delegate part or all of a method's execution to a superclass (even though we override the method, e.g. to provide extra features, the superclass's implementation is still needed as a part of our own). It's OK to do this explicitly to 'the' single superclass in question IF we know which one it is; but, particularly with multiple inheritance, we may not know (we may move methods between superclasses and don't want to depend on that in the subclass we're writing; we may need to call _all_ implementations in various direct superclasses of some method, particularly for special stuff such as __init__ and __del__).

The callbase function provides an example of a reasonably simple use of metaprogramming (introspection, aka reflection) -- it looks for the method by name in a given base-class, and calls it if found, with some typical tweaks (either ignore or raise a special error if not found). It can be called in a loop over __bases__ -- asking it to raise, and breaking the loop as soon as it doesn't raise, if we only want the first-found superclass implementation, or just looping all the way if we want all such implementations.

Like all 'practical' applications of metaprogramming to everyday programming tasks, this needs to be used with caution and good judgment -- it's VERY easy to get overboard with enthusiasm for such possibilities, and forget that simplicity is a key criterion!

2 comments

Matthew Wedgwood 18 years, 10 months ago  # | flag

Slightly more generalized. By changing:

for base in A.__bases__:

to:

for base in self.__class__.__bases__:

you get a version of the snippet that can be used in other classes without modification.

Ed Avis 18 years, 9 months ago  # | flag

super(). Does this need updating for Python 2.2 and its new super() function?

Created by Alex Martelli on Mon, 12 Mar 2001 (PSF)
Python recipes (4591)
Alex Martelli's recipes (27)
Python Cookbook Edition 1 (103)

Required Modules

  • (none specified)

Other Information and Tasks