如何装饰类或静态方法

时间:2016-02-09 12:49:12

标签: python decorator class-method

我正在编写一个泛型类装饰器,需要将装饰器应用于每个方法。我的第一种方法是这样的:

def class_decorator(cls):
    for name, member in vars(cls).items():
        # Ignore anything that is not a method
        if not isinstance(member, (types.FunctionType, types.BuiltinFunctionType, classmethod, staticmethod)):
            continue

        setattr(cls, name, method_decorator(member))

    return cls

装饰者本身并不是很重要。看起来像这样:

def method_decorator(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kwargs):
        # do something
        return fn(*args, **kwargs):

    return wrapper

一旦我测试了它,我遇到的问题是这不适用于静态或类方法,并且functools.wraps引发了以下错误:

AttributeError: 'classmethod' object has no attribute '__module__'

是的,classmethodstaticmethods不是正常功能,甚至不是callables。通常,如果您需要装饰classmethod,首先应用装饰器然后应用classmethod装饰器,但由于这是类装饰器,因此我不能影响装饰器的顺序。

对此有什么好的解决方案吗?

1 个答案:

答案 0 :(得分:3)

在玩了一会儿之后,我找到了一个比SO中的其他方法更好的解决方案。也许这对某些人有帮助。

基本上这个想法如下:

  • 检测类或静态方法的成员
  • 获取包含在这些方法中的函数对象
  • 将装饰器应用于此功能
  • 将装饰的功能包裹在classmethodstaticmethod实例
  • 再次将其存储在课堂中

代码如下所示:

def class_decorator(cls):
    for name, member in vars(cls).items():
        # Good old function object, just decorate it
        if isinstance(member, (types.FunctionType, types.BuiltinFunctionType)):
            setattr(cls, name, method_decorator(member))
            continue

        # Static and class methods: do the dark magic
        if isinstance(member, (classmethod, staticmethod)):
            inner_func = member.__func__
            method_type = type(member)
            decorated = method_type(method_decorator(inner_func))
            setattr(cls, name, decorated)
            continue

        # We don't care about anything else

    return cls