有没有一种方法可以将decorator应用于需要类信息的Python方法?

2024-04-27 03:47:48 发布

您现在位置:Python中文网/ 问答频道 /正文

当您修饰一个方法时,它还没有绑定到类,因此还没有im_class属性。我在寻找一种在decorator中获取类的信息的方法。我试过了:

import types

def decorator(method):

    def set_signal(self, name, value):
        print name
        if name == 'im_class':
            print "I got the class"

    method.__setattr__ = types.MethodType(set_signal, method)

    return method


class Test(object):
    @decorator
    def bar(self, foo):
        print foo

但它什么也不打印。在

我可以想象这样做:

^{2}$

但如果我能避免它,它将使我的一天。在


Tags: 方法nameself信息signal属性foodef
3条回答

我的严格回答是:这是不可能的,因为当decorator被执行时,类还不存在。在

更长的答案将取决于你非常确切的要求。正如我所写的,如果类还不存在,就不能访问它。一种解决方案是,标记装饰方法稍后将被“转换”。然后使用元类或类装饰器在类创建后应用修改。在

另一个选择是一些魔法。在zope.interfaces中查找implements方法的实现。它可以访问刚刚解析的类的信息。不知道对于你的用例来说是否足够。在

您可能想看看descriptors。它们允许您实现在访问属性时使用的__get__,并且可以根据对象及其类型返回不同的内容。在

__setattr__只在显式的object.attribute =赋值时调用;生成类不使用属性赋值,而是生成字典(Test.__dict__)。在

但要访问该类,您有几个不同的选项:

  1. 请改用类装饰器;它将在构建完成的类之后传递给它,您可以通过在类中替换(修饰)它们来装饰该类上的各个方法。可以使用函数装饰器和类装饰器的组合来标记要修饰的方法:

    def methoddecoratormarker(func):
        func._decorate_me = True
        return func
    
    def realmethoddecorator(func):
        # do something with func. 
        # Note: it is still an unbound function here, not a method!
        return func
    
    def classdecorator(klass):
        for name, item in klass.__dict__.iteritems():
            if getattr(item, '_decorate_me', False):
                klass.__dict__[name] = realmethoddecorator(item)
    

    当然,您可以使用元类而不是类装饰器来实现同样的效果。

  2. 欺骗,并使用^{}从调用帧中检索类:

    ^{pr2}$

    请注意,您所能检索到的只是类的名称;此时类本身仍在构建中。您可以向callingframe.f_locals(一个映射)添加项,它们将成为新类对象的一部分。

  3. 每当调用方法时访问selfself毕竟是对实例的引用,self.__class__将至少是定义函数的原始类的一个子类。

相关问题 更多 >