类和函数的装饰器

时间:2019-01-08 21:18:13

标签: python class decorator

我对Python装饰器有疑问。

class decorator(object):
    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        print('sth to log: %s : %s' % (self.function.__name__, args))
        return self.function(*args, **kwargs)


@decorator
def sum_test(a, b):
    print('sum: %s' % (a+b))

@decorator
class Class_test(object):
    def __init__(self):
        pass
    def sum_func(self, a, b):
        print('class sum: %s' % (a+b))
        return a+b

if __name__ == '__main__':
    sum_test(3, 4)
    func = Class_test()
    var1 = func.sum_func(1, 4)
    print(var1)

输出:

sth to log: sum_test : (3, 4)
sum: 7
sth to log: Class_test : ()
class sum: 5
5

装饰器正在按我想要的功能sum_test工作。我可以记录函数sum_test与变量34一起使用。

我在装饰类时遇到问题。我可以记录创建类Class_test的对象,但是我没有使用功能sum_func的信息。

为什么在类对象上运行__call__()时装饰器中的sum_func没有被触发,而直接在函数sum_test中使用时为什么被触发?

1 个答案:

答案 0 :(得分:0)

使用decorator装饰类意味着Class_test现在是decorator对象,因此Class_test.function是您为其编写主体的类。

请记住,@decorator语法是

的语法糖。
class Class_test(object):
    def __init__(self):
        pass
    def sum_func(self, a, b):
        print('class sum: %s' % (a+b))
        return a+b

Class_test = decorator(Class_test)

(除非Class_test符号从来没有指向您的班级)。

因此,在您调用decorator时会调用此Class_test对象,这恰好是您在日志中看到的:

sth to log: Class_test : ()
另一方面,

func.sum_func是常规绑定方法。它对decorator一无所知。

如果要在类中使用它,我更喜欢使用封闭式装饰器(返回函数的函数)。它返回的函数通常将由class机制注册为一个方法。

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print('sth to log: %s : %s' % (func.__name__, args))
        return func(*args, **kwargs)
    return wrapper

class Class_test(object):
    @decorator
    def sum_func(self, a, b):
        print('class sum: %s' % (a+b))
        return a+b

如果您仍然想使用基于类的方法,请阅读Python Class Based Decorator with parameters that can decorate a method or a function