【问题标题】:Decorator of classes and functions类和函数的装饰器
【发布时间】:2019-01-08 21:18:12
【问题描述】:

我的 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 的信息。

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

【问题讨论】:

  • 旁注:我建议在函数内部使用闭包而不是完整的
  • 你希望装饰器在应用于类时做什么?是不是要装饰类的每一个方法?
  • 一般来说,你不能将相同的装饰器应用到函数和类——尽管通过一些巧妙的编码可能是可能的。
  • 我想让装饰器记录哪些函数和类与变量一起使用。我应该有另一个装饰师上课吗?我可以为 sum_func 类的函数再添加一个装饰器吗?

标签: python class decorator


【解决方案1】:

使用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 符号绝不代表您的班级)。

因此,当您调用 Class_test 时会调用此 decorator 对象,这正是您在日志中看到的情况:

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

【讨论】:

  • 我应该为课堂使用不同的装饰器吗?我在类中直接装饰函数时遇到问题:return self.function(*args, **kwargs) TypeError: sum_func() missing 1 required positional argument: 'b' 如何告诉装饰器将函数返回到该类?跨度>
  • @Pablo 我在答案中添加了一个部分来解决这个问题。
猜你喜欢
  • 2011-06-06
  • 2016-07-04
  • 2011-10-04
  • 2021-12-29
  • 2015-10-23
  • 2021-06-24
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多