繁体   English   中英

如何将装饰器应用于超类的方法?

[英]How do I apply decorators to a superclass's methods?

假设我有一个python类

class Foo(object):
    def method1(self, x):
        print("method1 called with %s" %(x,))

    def method2(self, x):
        print("method2 called with %s" %(x,))

和一个装饰

def myDecorator(func):
    newFunc = someModificationOf(func)
    return newFunc

我希望能够子类化Foo并且在子类定义中以某种方式表明我希望myDecorator应用于从Foo继承的方法的某个子集。 例如,我的子类可能喜欢

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 我喜欢使用元类的想法,因为它允许装饰器操作函数而不是方法,这似乎是一个很好的简化。

我假设你真正想做的不是装饰基类的那些方法的副本,而是装饰子类中这些方法的新重写副本。

如果是这样,那很容易。 传递给元类的字典中不存在这些方法,因为它们没有在类定义中定义,它们是从基类继承的。 哪个元类可以访问。 所以:

def __new__(cls, name, bases, d):
    def find_method(m):
        for base in bases:
            try:
                return getattr(base, m)
            except AttributeError:
                pass
        raise AttributeError("No bases have method '{}'".format(m))
    for m in d['methodsToDecorate']:
        d[m] = myDecorator(find_method(m))
    return type(name, bases, d)

如果你确实想要进入基类并替换它的方法,你当然可以使用相同的技巧。 只是找到方法一起返回基地,这样你就可以setattr它。


您要求覆盖基类中的方法。 但是,如果该方法实际上来自更远的祖先呢? 然后这仍然有效...但它可能无法按您想要的方式工作。 如果您有多个共享共同祖先的基础,则在每个直接基础上调用getattr在每个基础上搜索该共同祖先一次,但在新类上调用getattr将仅在最后搜索一次。

正如user2357112在注释中指出的那样,如果你要覆盖的是“如果我没有覆盖任何东西就会被调用的东西”,你可以构建新类,然后通过调用后修改它来做到这一点。结果类本身的getattr 在2.x中,这是否意味着你必须处理与非绑定方法,而不是功能(在3.x中,这不是一个问题,因为非绑定方法仅仅函数),但收益可能大于成本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM