假设我有一个python类
class Foo(object):
def method1(self, x):
print("method1 called with %s" %(x,))
def method2(self, x):
print("method2 called with %s" %(x,))
还有一个装修工
^{pr2}$我希望能够将Foo
子类化,并且在子类定义中,我希望myDecorator
应用于从{
class Baz(Foo):
methodsToDecorate = ['method2']
这可能吗?在
我尝试了:
我想我可以用元类来做这个:
class Baz(Foo):
__metaclass__ = Meta
methodsToDecorate = ['method2']
class Meta(type):
def __new__(cls, name, bases, d):
for m in d['methodsToDecorate']:
d[m] = myDecorator(d[m])
return type(name, bases, d)
但是,它不起作用,因为'method2'
不在传递给元类的__new__
方法的字典中,所以我们得到一个KeyError
。我喜欢使用元类的想法,因为它允许装饰者操作函数,而不是方法,这看起来是一个很好的简化。在
我假设您真正想要做的不是修饰基类的那些方法的副本,而是在子类中装饰这些方法的新的重写副本。在
如果是这样,那就很容易了。方法在传递给元类的字典中不存在,因为它们不是在类定义中定义的,而是从基继承的。元类也可以访问。所以:
如果您真的想访问基类并替换它的方法,当然可以使用相同的技巧。只需返回base和found方法,这样就可以
setattr
它。在您请求重写基类中的方法。但是如果这个方法真的来自一个更遥远的祖先呢?那么这仍然有效…但它可能无法按你想要的方式工作。如果有多个基共享一个共同的祖先,那么在每个直接基上调用
getattr
将在每个基上搜索该共同祖先一次,但在新类上调用getattr
只会在最后搜索一次。在正如user2357112在一条注释中指出的,如果您想要重写的是“如果我没有重写任何内容,将会调用什么”,那么您可以先构造新类,然后在事实发生后修改它,方法是在result类本身上调用
getattr
。在2.x中,这意味着您必须处理未绑定的方法而不是函数(在3.x中,这不是问题,因为未绑定的方法只是是函数),但好处可能大于成本。在相关问题 更多 >
编程相关推荐