I l@ve RuBoard Previous Section Next Section

15.7 Modifying Methods in Place

Credit: Ken Seehof

15.7.1 Problem

You need to globally change the behavior of existing classes in a third-party library梖or example, by wrapping existing _ _init_ _ methods.

15.7.2 Solution

Avoid the antipattern of modifying library code, even though you have source for it, or you'll be forever chasing upgrades to the library and reapplying your changes to each release. Python's introspection lets you noninvasively obtain the same desired effect without changing the library's source code:

# needs Python 2.1 or later
from _ _future_ _ import nested_scopes
import new

def enhance_ _init_ _(klass, f):
    try: ki = klass._ _init_ _
    except AttributeError:
        def ki(self, *args, **kwds): pass
    klass._ _init_ _ = new.instancemethod(
        lambda *args, **kwds: f(ki, *args, **kwds), None, klass)

def demo(  ):
    class X:
        def _ _init_ _(self, v):
            self.v = v

    def g(_ _init_ _, self, v):
        _ _init_ _(self, v)

    enhance_ _init_ _(X, g)

    x = X(2)
    print x.parrot

demo(  )

15.7.3 Discussion

Once in a while it becomes necessary to globally change the behavior of classes in a third-party library, ideally without modifying the source code for that library. This recipe demonstrates the ability to modify the _ _init_ _ method of an arbitrary class in place at runtime by wrapping the method in any given metafunction. In my experience, this approach is also good for making functional programmers wince, which can be entertaining.

Of course, many other forms of currying besides the lambda used in this recipe could be used to build the underlying function for the enhanced method.

15.7.4 See Also

Recipe 15.8 for currying in general; Recipe 5.14 and Recipe 15.10 for other examples of modifying the methods of an instance; antipatterns (patterns that tell how to go from a problem to a bad solution) are discussed in detail on the Portland Pattern WikiWiki (http://c2.com/cgi/wiki?AntiPatterns).

    I l@ve RuBoard Previous Section Next Section