voodoo: modifying class methods a posteriori

Paul Winkler slinkp23 at yahoo.com
Wed Sep 19 07:49:13 CEST 2001

On Tue, 18 Sep 2001 18:00:32 -0000, hungjunglu at yahoo.com wrote:
>Now, all that is nice. BUT, usually, when you override a method, you 
>probably want to do just a bit more than what the old method was 
>Is there a way of doing the same thing without subclassing?

This is exactly what the Decorator design pattern is for.  Note: I
only just learned about Decorators today, so don't take this as gospel
- I may have misunderstood something. But the following seems to work,
it satisfies the criteria of the Decorator as I understand it, and it
does exactly what you're asking for:

class Decorator:
    """An abstract Decorator class based on one posted to comp.lang.python
    by Rainer Deyke.
    def __init__(self, decorated):
        self._decorated = decorated
    def __getattr__(self, name):
        return getattr(self._decorated, name)
    def __call__(self, *args, **kwargs):
        self._decorated(*args, **kwargs)
    # Override other operators too.

class MyDecorator(Decorator):
    def f(self):
        print "before saying something"
        print "after saying something"

class A:
    def __init__(self):
        self.foo = "I am an attribute of A."
    def f(self):
        print 'Hello from A.f()'

# Now let's test it.
a = MyDecorator(A())
# Note that a now behaves identically to an instance of A in
# all respects, except that we've "decorated" one method.

print a.foo

# end script

Here's the output that produces:

before saying something
Hello from A.f()
after saying something
I am an attribute of A.

Note a couple of things that make this really cool:

1) you can use any number of decorators chained together in any
combination, e.g.

a = Decorator1(Decorator2(Decorator3(A())))

Since you'll get different results depending on what order you put the
decorators in, defining 3 decorators gives you ... uh... 15 unique
combinations of 1 to 3 decorators. Compare that to making 15
subclasses of A to get the same flexibility.

2) you can use the same decorators for any number of different objects
as long as they provide the method(s) you're decorating.


More information about the Python-list mailing list