python - Python - 元类装饰器 - 如何使用 @classmethod
问题描述
我有以下 Python 元类,它deco_with_args
为每个类添加了一个装饰器:
def deco_with_args(baz):
def decorator(func):
...
return func
return decorator
class Foo(type):
def __prepare__(name, bases):
return {'deco_with_args': deco_with_args}
这允许我像这样使用装饰器:
class Bar(metaclass=Foo):
@deco_with_args('baz')
def some_function(self):
...
如何使deco_with_args
装饰器表现得像 an@classmethod
以便我可以Bar
从函数内访问该类(或任何其他类)decorator
?
我试过@classmethod
在deco_with_args
函数上使用没有运气。
解决方案
您的问题有两种解释-如果您需要在调用示例中cls
命名的函数时可用decorator
(即,您需要修饰的方法成为类方法),则将其本身转换为类方法就足够了:
def deco_with_args(baz):
def decorator(func):
...
return classmethod(func)
return decorator
第二个是如果您需要在调用自身时cls
可用deco_with_args
,在创建装饰函数本身时,在类创建时。现在被列为已接受的答案列出了一个简单的问题:当类主体运行时,该类还不存在,因此,在解析类主体结束时,您不可能拥有将知道类本身。
但是,与该答案试图暗示的不同,这不是真正的交易。cls
您所要做的就是在类创建过程结束时懒惰地运行您的装饰器代码(需要. 你已经有一个元类设置,所以这样做几乎是微不足道的,只需在你的装饰器代码周围添加另一个可调用层:
def deco_with_args(baz):
def outter_decorator(func):
def decorator(cls):
# Code that needs cls at class creation time goes here
...
return func
return decorator
outter_decorator._deco_with_args = True
return outter_decorator
class Foo(type):
def __prepare__(name, bases):
return {'deco_with_args': deco_with_args}
def __init__(cls, cls_name, bases, namespace, **kwds):
for name, method in cls.__dict__.items():
if getattr(method, '_deco_with_args', False):
cls.__dict__[name] = method(cls)
super().__init__(cls_name, bases, namespace, **kwds)
当然,这将在类主体执行完成之后运行,但在class
运行之后的任何其他 Python 语句之前。如果您的装饰器会影响在类主体内部执行的其他元素,那么您需要做的就是将它们包装起来以保证延迟执行。
推荐阅读
- angular - Angular:订阅中的单元测试变量
- ios - IOS 应用程序终止时终止 chromecast 会话
- reactjs - 与 useReducer 一起使用时,useEffect 不会触发重新渲染
- c# - 给定 C# 中已知的 DPI,如何计算以毫米为单位的给定字体大小?
- ocaml - 致命错误:调试器不支持通道锁
- nltk - 即使使用 POS 标签,Nltk Wordnet 也不会对单词进行词形还原
- python - tf.keras“历史未定义”......但在我看来它已被定义
- java - EasyRandom 集合大小错误?
- swift - SwiftUI 中 CoreData 列表项的详细视图
- java - Java Micrometer @Counted - @ExceptionHandler 的 exception="none" 和 result="success"?