【问题标题】:How to decorate class or static methods如何装饰类或静态方法
【发布时间】:2016-05-19 11:13:18
【问题描述】:

我正在编写一个通用类装饰器,它需要对每个方法应用一个装饰器。我的第一种方法是这样的:

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 不是普通函数,甚至不是可调用函数。一般来说,如果你需要装饰一个classmethod,你首先应用你的装饰器,然后是classmethod装饰器,但由于这是一个类装饰器,我无法影响装饰器的顺序。

有什么好的解决方案吗?

【问题讨论】:

  • 因为装饰器造成歧义:绑定对象的类方法不是函数对象(装饰器返回的),所以无法将方法绑定到类

标签: python decorator class-method


【解决方案1】:

玩了一段时间后,我找到了一个比 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

【讨论】:

    猜你喜欢
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 2019-11-06
    • 2015-02-21
    相关资源
    最近更新 更多