如何在运行时获取函数的decorator名称?

时间:2017-12-07 06:33:55

标签: python decorator python-decorators

在以下代码中,类print_a的方法(print_bTest)已由两个不同的装饰器修饰。

如何确定给定方法(比如说print_a)是否在运行时装饰了一些特定的装饰器(decorator1)?

简单的解决方案是更改包装函数的名称,即在装饰器方法中将wrapper更改为wrapper1wrapper2,但问题是我不知道t可以控制代码的那一部分。

python是否有像Java这样的反射API,这对我有帮助吗?

def my_decorator1(func):
    def wrapper(*args, **kwargs):
        print('I am decorated:1')
        func(*args, **kwargs)
    return wrapper

def my_decorator2(func):
    def wrapper(*args, **kwargs):
        print('I am decorated:2')
        func(*args, **kwargs)
    return wrapper

class Test():

    def __init__(self, a=None, b=None):
        self.a = a
        self.b = b

    @my_decorator1
    def print_a(self):
        print('Value of a is {}'.format(self.a))

    @my_decorator2
    def print_b(self):
        print('Value of b is {}'.format(self.b))


if __name__ == '__main__':

    d = Test.__dict__

    f1 = d.get('print_a')
    f2 = d.get('print_b')

2 个答案:

答案 0 :(得分:3)

由于装饰器功能在装饰时执行,因此很难获得名称。您可以使用其他装饰器来解决您的问题。装饰器annotator写入函数的属性,您可以在装饰函数中读取此名称:

def annotator(decorator):
    def wrapper(f):
        g = decorator(f)
        g.decorator = decorator.__name__
        return g
    return wrapper

@annotator(my_decorator1)
def x():
    print x.decorator

答案 1 :(得分:1)

Python装饰器更多的是关于转换函数而不是简单的元数据标签,就像Java注释一样。所以为了做到这一点,我让装饰器在它正在包装的函数上设置一个属性(或者可能将它包装在特定类型的可调用函数中):

def my_decorator1(func):
    def wrapper(*args, **kwargs):
        print('I am decorated:1')
        func(*args, **kwargs)
    wrapper.decorator_name = 'my_decorator1'
    return wrapper

然后:

print(Test.print_a.decorator_name)

或者,在Python 3.3+中,您可以使用PEP 3155' __qualname__来识别装饰器。