voodoo: modifying class methods a posteriori

hungjunglu at yahoo.com hungjunglu at yahoo.com
Tue Sep 18 14:00:32 EDT 2001


Hi,

This is a problem that has bugged me for a while, now. (Related topic 
might be "function closure", which I don't understand much.)

What follows is pure Python voodoo. But when voodoo is used properly, 
it does wonders. :)

Say, you have a class "A" with method "f(self)" (which potentially 
could be the constructor __init__() or destructor __del__(), by the 
way.)

Instance-bound methods can be overriden easily. (I am not interested 
in derived subclass, see the reason a bit later.)

class A:
  def f(self):
    print 'hello'
def g(self):
  print 'bye'
a = A()
a.f()
import new
a.f = new.instancemethod(g, a, A)
a.f()

The class-bound method f() can be overriden, easily, too:

class A:
  def f(self):
    print 'Hello'
def g(self):
  print 'Bye'
a = A()
a.f()
A.f.im_func.func_code = g.func_code
a.f()

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. Say, you may only want to add a print statement when the 
method is called, or you may want to insert a statement to the 
constructor/destructor so object instances can automatically 
register/deregister to a particular event handler.

When you have many subclasses derived from subclasses of other 
classes, especially when you don't have access to the source code for 
one reason or another, or when you don't want to or you can't modify 
the source code of the superclass, is there a way of inserting 
statements into the class methods?

In derived class, what you would do is something like:

class A:
  def f(self):
    print 'Hello'
class AA(A):
  def f(self):
    print 'before saying Hello'
    A.f(self)
    print 'after saying Hello'
a = AA()
a.f()

Notice you are able to insert statements before and after the base 
class method call.

Is there a way of doing the same thing without subclassing?

=============

hmm.... I think I just answered myself, I'll post it to the mailing 
list anyway:

class A:
  def f(self):
    print 'Hello'
def g(self):
    print 'before saying Hello'
    self.f_old()
    print 'after saying Hello'
a = A()
a.f()
import new
A.f_old = A.f
A.f = new.instancemethod(g, None, A)
a.f()

=====================

Wow! It's fun! I wonder why people are still using Java. :)

Hung Jung






More information about the Python-list mailing list