adding class functionality, nested scoping

jholg at gmx.de jholg at gmx.de
Fri Jan 4 05:43:46 EST 2008


Hi,

regarding automatically adding functionality to a class (basically taken
from the cookbook recipee) and Python's lexical nested scoping I have a question wrt this code:

#-----------------
import types

# minor variation on cookbook recipee
def enhance_method(cls, methodname, replacement):
    'replace a method with an enhancement'
    method = getattr(cls, methodname)
    def _f(*args, **kwargs):
        return replacement(method, *args, **kwargs)
    _f.__name__ = methodname
    setattr(cls, methodname, types.MethodType(_f, None, cls))
    
# loop over class dict and call enhance_method() function
# for all methods to modify
def enhance_all_methods(cls, replacement):
    for methodname in cls.__dict__:
        if not methodname.startswith("__"):
            method = getattr(cls, methodname)
            def _f(*args, **kwargs):
                return replacement(method, *args, **kwargs)
            _f.__name__ = methodname
            enhance_method(cls, methodname, replacement)


# Does not work: all enhanced methods only call the last wrapped originial
# method. It seems the name 'method' in the surrounding scope of the
# def _(...) function definition only refers to the last loop value(?)
def ERRONEOUS_enhance_all_methods(cls, replacement):
    for methodname in cls.__dict__:
        if not methodname.startswith("__"):
            method = getattr(cls, methodname)
            def _f(*args, **kwargs):
                return replacement(method, *args, **kwargs)
            _f.__name__ = methodname
            setattr(cls, methodname, types.MethodType(_f, None, cls))

            
class Foo(object):
    def foo(self, x):
        print "foo", x
    
    def bar(self, x):
        print "bar", x


def logme(method, *args, **kwargs):
    print "-->", method.__name__, args, kwargs
    try:
        return method(*args, **kwargs)
    finally:
        print "<--"


#enhance_all_methods(Foo, logme)        
ERRONEOUS_enhance_all_methods(Foo, logme)

foo = Foo()
foo.foo(2)
foo.bar(2)
#-----------------

...give this output:
>>> foo = Foo()
>>> foo.foo(2)
--> foo (<__main__.Foo object at 0x1b08f0>, 2) {}
foo 2
<--
>>> foo.bar(2)
--> foo (<__main__.Foo object at 0x1b08f0>, 2) {}
foo 2
<--
>>>

So, while using enhance_all_methods() to add functionality does work, ERRONEOUS_enhance_all_methods() does not. Why is this? Is the explanation I tried to give in the code comment on the right track:

# Does not work: all enhanced methods only call the last wrapped originial
# method. It seems the name 'method' in the surrounding scope of the
# def _(...) function definition only refers to the last loop value(?)

Thanks for any hint,
Holger
-- 
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger?did=10



More information about the Python-list mailing list