voodoo: modifying class methods a posteriori
Paul Winkler
slinkp23 at yahoo.com
Wed Sep 19 01:49:13 EDT 2001
On Tue, 18 Sep 2001 18:00:32 -0000, hungjunglu at yahoo.com wrote:
(snip)
>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
>doing.
(snip)
>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"
self._decorated.f()
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.
a.f()
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.
--PW
More information about the Python-list
mailing list