If each class's __init__ is used to set default values, it requires that one use super() or explicit parentclass.__init__() calls . Such ugly boilerplate can be avoided with this recipe.
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 34 35 36 37 38 39 40 41 42 43 44 45 46
class Base(object): def __init__(self, *args, **kwds): self.autosetup(self.__class__, , **kwds) def setup(self, **kwds): pass def autosetup(self, cls, called, **kwds): for base in cls.__bases__: try: b = base.setup except AttributeError: pass else: if b not in called: called = self.autosetup(base, called, **kwds) cls.setup(self, **kwds) called.append(cls.setup) return called # Sample Usage class A(Base): def setup(self, foo, **kwds): print "A",foo class B(Base): def setup(self, blah, **kwds): print "B", blah class C(B): def setup(self, blech, **kwds): print "C", blech class D(A, C): def setup(self, frog, **kwds): print "D", frog class E(C): pass class F(D, E): def setup(self, toad, foo, frog, **kwds): print "F", foo, frog, toad x = F(foo=1, blah=2, blech=3, frog=4, toad=5)
Using super() is ugly and painful, and for one of the most common cases - allowing classes to set default values - unnecessary.
It was originally created for game objects where a user class can inherit from a large number of mixins, eg: "Cake(Base, CanWriteOn, CanBurn, CanTake, CanEat)...", but should be of general use. The same technique could be used to do an autoverify() after the autosetup(), to check values set by the user that aren't otherwise checked.
There's some discussion on using super() at http://mail.python.org/pipermail/python-dev/2005-January/050656.html
Tim Delaney has an autosuper recipe at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286195