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 -- http://mail.python.org/mailman/listinfo/python-list