You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Python类中的装饰器方法转换为独立类

类内装饰器方法转独立装饰器类的错误修正

原可运行代码(补全必要语法和导入)

from functools import wraps

class MyClass():

    class Decorators():

        @classmethod
        def dekarait(cls, func):

            @wraps(func)
            def wrapper(instance, name: str, count: int = 0):
                print(name * count)
                func(instance)

            return wrapper

    def __init__(self) -> None:
        pass

    @Decorators.dekarait
    def good(self, name: str, count: int = 0) -> str:
        out: str = f"name:{name}"
        print("hello")
        return out

错误尝试代码

class MyClass():

    class Dekarait():

        def __init__(self, func):
            self.func = func

        def __call__(self, func):
            def wrapper(self, name: str, count: int = 0):
                print(name * count)
                func()

            return wrapper

    def __init__(self) -> None:
        pass

    @Dekarait
    def good(self, name: str, count: int = 0) -> str:
        out: str = f"name:{name}"
        print("hello")
        return out

问题核心分析

你没搞懂类作为装饰器的执行逻辑,错误点集中在:

  1. __call__参数逻辑错误:用@Dekarait装饰方法时,会先创建Dekarait实例并保存被装饰的good方法;调用obj.good(...)时,实际是调用Dekarait实例的__call__,此时传入的是MyClass实例、name、count,而非错误的func参数。
  2. 实例方法调用缺失绑定:原good是实例方法,必须绑定MyClass实例才能执行,错误代码里func()没传实例参数,必然报错。
  3. 变量名冲突:wrapper里的self和Dekarait类的self重名,导致逻辑混淆。

修正后的代码

from functools import wraps

class MyClass():

    class Dekarait():
        def __init__(self, func):
            self.func = func
            wraps(func)(self)  # 保留原函数的名称、文档等元信息

        def __call__(self, instance, name: str, count: int = 0):
            # instance是MyClass的实例,对应原方法的self
            print(name * count)
            # 调用原方法必须传入实例,绑定实例方法
            return self.func(instance, name, count)

    def __init__(self) -> None:
        pass

    @Dekarait
    def good(self, name: str, count: int = 0) -> str:
        out: str = f"name:{name}"
        print("hello")
        return out

关键修改点说明

  • __call__参数调整:明确接收MyClass实例作为第一个参数,后续是原方法的参数,符合装饰实例方法的调用逻辑。
  • 实例方法绑定调用:通过self.func(instance, name, count)给原方法传入实例,保证实例方法能正常执行。
  • 元信息保留:用wraps(func)(self)复制原函数的元信息,避免装饰后函数名称、文档等被覆盖。
  • 变量名清晰化:用instance代替容易混淆的self,明确区分装饰器类实例和MyClass实例。

测试验证

运行以下代码可正常输出:

obj = MyClass()
result = obj.good("test", 3)
# 输出:testtesttest
#      hello
print(result)  # 输出:name:test

内容的提问来源于stack exchange,提问作者matt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:50:26