我想从装饰器中更新一个“类范围”列表,它装饰类的方法,并将每个修饰的方法添加到该列表中。
这就是我所想到的:
def add(meth: callable):
Spam.eggs.append(func)
return meth
class Spam:
eggs = []
@add
def meth(self):
pass但是,这是行不通的,因为Spam还没有完成在到达@add时定义自己的工作,因此add会引发一个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我可以手动在列表中添加方法,但是我发现装饰器更清晰,因为它接近于方法的定义,因此在定义新方法时要比手动将它添加到列表中更容易记住。
发布于 2019-07-10 18:38:26
您的当前方法失败了,因为当transform_meth被调用时,TextProcessor还没有绑定到任何东西(或者如果是,则在class语句完成时该对象会被覆盖)。
简单的解决方案是在transform_meth语句中定义class,这样它就可以简单地将transforms声明为一个非局部变量。但是,这是行不通的,因为class语句没有建立新的作用域。
相反,您可以定义一个创建装饰符的函数,该函数接受所需的列表(此时仅是class语句正文中的一个名称,而不是任何假定范围中的名称)。该函数在list参数上返回一个闭包,以便您可以附加到它。
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 attributehttps://stackoverflow.com/questions/56976329
复制相似问题