Python中的实例方法装饰器
我想做的事情大概是这样的。我有一个对象的列表,我知道这些对象里面有一个实例方法,长得像这样:
def render(self, name, value, attrs)
# Renders a widget...
我想在运行时,也就是在遍历这个对象列表的时候,给这些函数加点装饰。这样它们的渲染函数就变成这样:
def render(self, name, value, attrs)
self.attrs=attrs
# Renders a widget...
有两个注意事项:
- 这个渲染函数是django框架的一部分。我不能在他们的库里面加装饰器(其实可以,但那样我就得自己维护和迁移这个改动)。
- 这是一个实例方法。
这里有个例子:
http://wiki.python.org/moin/PythonDecoratorLibrary这个链接展示了如何给一个类添加新的实例方法。我的不同之处在于,我想在记住那个attrs参数之后,继续调用原来的方法。
2 个回答
3
传统的做法是通过子类来实现。这种方式可以避免去修改别人写的类。
class someclass(object):
def render(self, name, value, attrs):
print hasattr(self, 'attrs')
class my_render(object):
def render(self, name, value, attrs):
self.attrs = attrs # kind of decorating the function here
return super(my_render, self).render(name, value, attrs)
class my_class(my_render, someclass):
pass
someclass().render(1,2,3) # -> False
my_class().render(1,2,3) # -> True
使用多重继承的原因是所有的类都可以从 my_render
这个类继承。我个人很喜欢这种混合的概念;-)
class my_otherclass(my_render, someotherclass): pass
class my_thirdclass(my_render, thirdclass): pass
# or less explicit
classlist = [ someclass, someotherclass ]
newclasses = [ type('my_'+cls.__name__, (my_render,cls), {}) for cls in classlist ]
7
def decorate_method(f):
def wrapper(self, name, value, attrs):
self.attrs = attrs
return f(self, name, value, attrs)
return wrapper
def decorate_class(c):
for n in dir(c):
f = getattr(c, n)
if hasattr(f, 'im_func'):
setattr(c, n, decorate_method(f.im_func))
你可能还需要一些其他的测试来跳过那些参数不同的方法,不过除此之外,decorate_class(whatever)
应该可以在任何你给定的类 whatever
上实现你想要的功能。