如何装饰class或静态方法
How to decorate class or static methods
我正在编写一个通用的 class 装饰器,它需要为每个方法应用一个装饰器。我的第一种方法是这样的:
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
一旦我测试了它,我 运行 遇到了这个问题,即这不适用于静态或 class 方法,并且从 functools.wraps
:[=19 引发了以下错误=]
AttributeError: 'classmethod' object has no attribute '__module__'
是的,classmethod
或 staticmethods
不是普通函数,甚至不是可调用函数。一般来说,如果你需要装饰一个 classmethod
,你首先应用你的装饰器,然后应用 classmethod
装饰器,但由于这是一个 class 装饰器,我无法影响装饰器的顺序。
有什么好的解决办法吗?
玩了一会儿之后,我找到了一个在我看来比 SO 中的其他方法更好的解决方案。也许这对某人有帮助。
基本上思路是这样的:
- 检测 class 或静态方法
的成员
- 获取包含在这些方法中的函数对象
- 将装饰器应用于此函数
- 将装饰函数包装在
classmethod
或 staticmethod
实例中
- 再次将其存储在class中
代码如下所示:
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
我正在编写一个通用的 class 装饰器,它需要为每个方法应用一个装饰器。我的第一种方法是这样的:
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
一旦我测试了它,我 运行 遇到了这个问题,即这不适用于静态或 class 方法,并且从 functools.wraps
:[=19 引发了以下错误=]
AttributeError: 'classmethod' object has no attribute '__module__'
是的,classmethod
或 staticmethods
不是普通函数,甚至不是可调用函数。一般来说,如果你需要装饰一个 classmethod
,你首先应用你的装饰器,然后应用 classmethod
装饰器,但由于这是一个 class 装饰器,我无法影响装饰器的顺序。
有什么好的解决办法吗?
玩了一会儿之后,我找到了一个在我看来比 SO 中的其他方法更好的解决方案。也许这对某人有帮助。
基本上思路是这样的:
- 检测 class 或静态方法 的成员
- 获取包含在这些方法中的函数对象
- 将装饰器应用于此函数
- 将装饰函数包装在
classmethod
或staticmethod
实例中 - 再次将其存储在class中
代码如下所示:
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