python - 如何使用装饰器将类的方法添加到类内的列表中
问题描述
我想从装饰类的方法并将每个装饰方法添加到该列表的装饰器中更新“类范围”列表。
这就是我想到的:
def add(meth: callable):
Spam.eggs.append(func)
return meth
class Spam:
eggs = []
@add
def meth(self):
pass
但这不起作用,因为在达到Spam
时尚未完成自我定义@add
,因此如评论中所指出的那样add
引发 a 。NameError
我还尝试了一个类方法:
class Spam:
eggs = []
@classmethod
def add(cls, meth: callable):
cls.eggs.append(meth)
return meth
@add
def meth(self):
pass
但这也不起作用,因为当@add
到达时,add
它绑定到classmethod
不可调用的装饰实例。
这是我需要的:
我有一个带有几个方法的类,这些方法接受一个参数(除了self
),这些方法以这样一种方式转换该对象,使这些方法可以相互组合。我想以这样的方式装饰它们中的每一个,使它们自动添加到类中的列表中。
例如:
from typing import List
def transform_meth(meth: callable):
TextProcessor.transforms.add(meth)
return meth
class TextProcessor:
transforms: List[callable] = []
@transform_meth
def m1(self, text):
return text
@transform_meth
def m2(self, text):
return text
def transform(self, text):
for transform in self.transforms:
text = transform(text)
return text
我可以手动在列表中添加方法,但我发现装饰器更清晰,因为它接近方法的定义,因此在定义新方法时记住装饰新方法比将其添加到列表中更容易手动。
解决方案
您当前的方法失败了,因为 whentransform_meth
被调用,TextProcessor
还没有绑定到任何东西(或者如果是,该对象在class
语句完成时被覆盖)。
简单的解决方案是transform_meth
在语句内部定义class
,以便它可以简单地声明transforms
为非局部变量。但是,这行不通,因为class
语句没有建立新的范围。
相反,您可以定义一个创建装饰器的函数,该函数采用所需的列表(此时只是class
语句主体中的一个名称,而不是来自任何假定的范围)。该函数在列表参数上返回一个闭包,以便您可以附加到它。
def make_decorator(lst):
# *This* will be the function bound to the name 'transform_meth'
def _(meth):
lst.append(meth)
return meth
return _
class TextProcessor:
transforms: List[callable] = []
transform_meth = make_decorator(transforms)
@transform_meth
def m1(self, text):
return text
@transform_meth
def m2(self, text):
return text
def transform(self, text):
for transform in self.transforms:
text = transform(text)
return text
del transform_meth # Not needed anymore, don't create a class attribute
推荐阅读
- jmeter - jmeter记录器:如何在不创建新项目的情况下清除并重新开始记录
- python - 具有独立索引的动态数据透视表
- android - 为什么添加listView显示数据后应用崩溃
- reactjs - SVG 以错误的颜色显示
- php - 有时在脚本执行中数据库正在更新
- javascript - 如何检测 D3 v5(文本重叠)中的元素冲突
- c - 当大括号括起来的列表中的初始值设定项少于聚合的元素或成员时,C 编译器如何声明数组?
- python - 如何将 CSV 转换为固定宽度的文本文件?
- amazon-web-services - AWS 上的 Helm prometheus 自定义负载均衡器配置
- security - 访问令牌和刷新令牌最佳实践?如何实现访问和刷新令牌