Arnaud Delobelle
1/4/2008 11:20:00 AM
On Jan 4, 10:43 am, jh...@gmx.de wrote:
> Hi,
Hi
[...]
> # 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))
>
This is normal: After ERRONEOUS_enhance_all_methods is called, the
value method is the one from the last iteration of the loop. All
subsequent references to 'method' (in function _f) will return that
last value. To solve this problem you need to fix the object 'method'
is bound to in function _f:
def enhance_all_methods(cls, replacement):
# The following binds 'method' to its current value in _f
def replace(method):
def _f(*args, **kwargs):
return replacement(method, *args, **kwargs)
return _f
for methodname in cls.__dict__:
if not methodname.startswith("__"):
_f = replace(getattr(cls, methodname))
_f.__name__ = methodname
setattr(cls, methodname, types.MethodType(_f, None, cls))
Of course this looks more like your first version, which trims down to
the following and is probably a better option:
def enhance_all_methods(cls, replacement):
for methodname in cls.__dict__:
if not methodname.startswith("__"):
enhance_method(cls, methodname, replacement)
HTH
--
Arnaud