首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用装饰器将类的方法添加到类内的列表中

如何使用装饰器将类的方法添加到类内的列表中
EN

Stack Overflow用户
提问于 2019-07-10 18:05:29
回答 2查看 778关注 0票数 0

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

这就是我所想到的:

代码语言:javascript
复制
def add(meth: callable):
    Spam.eggs.append(func)
    return meth

class Spam:
    eggs = []

    @add
    def meth(self):
        pass

但是,这是行不通的,因为Spam还没有完成在到达@add时定义自己的工作,因此add会引发一个NameError,正如注释中指出的那样。

我还尝试了一个类方法:

代码语言:javascript
复制
class Spam:
    eggs = []

    @classmethod
    def add(cls, meth: callable):
        cls.eggs.append(meth)
        return meth

    @add
    def meth(self):
        pass

但是这也不起作用,因为当到达@add时,add被绑定到classmethod修饰的实例,这个实例是不可调用的。

我需要这个是为了:

我有一个类,它有几个使用一个参数(除了self)的方法来转换该对象,这些方法可以相互组合。我想用这样的方式来装饰它们,使它们自动添加到类中的列表中。

例如:

代码语言:javascript
复制
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

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

EN

Stack Overflow用户

回答已采纳

发布于 2019-07-10 18:38:26

您的当前方法失败了,因为当transform_meth被调用时,TextProcessor还没有绑定到任何东西(或者如果是,则在class语句完成时该对象会被覆盖)。

简单的解决方案是在transform_meth语句中定义class,这样它就可以简单地将transforms声明为一个非局部变量。但是,这是行不通的,因为class语句没有建立新的作用域。

相反,您可以定义一个创建装饰符的函数,该函数接受所需的列表(此时仅是class语句正文中的一个名称,而不是任何假定范围中的名称)。该函数在list参数上返回一个闭包,以便您可以附加到它。

代码语言:javascript
复制
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
票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56976329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档