首页 > 解决方案 > 如何使用装饰器将类的方法添加到类内的列表中

问题描述

我想从装饰类的方法并将每个装饰方法添加到该列表的装饰器中更新“类范围”列表。

这就是我想到的:

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

我可以手动在列表中添加方法,但我发现装饰器更清晰,因为它接近方法的定义,因此在定义新方法时记住装饰新方法比将其添加到列表中更容易手动。

标签: pythondecoratorclass-members

解决方案


您当前的方法失败了,因为 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

推荐阅读