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

Python装饰器类方法报错求助:'str'对象不可调用

问题分析与修复

错误原因

你编写的wrapper_f装饰器逻辑完全错误:

  • 调用k.add('hello')时,实际执行的是wrapper函数,它把传入的字符串'hello'误当作参数f(wrapper的参数定义为self, f: tp.Callable, *args, **kwargs)
  • 随后wrapper尝试调用f(self, *args, **kwargs),但f是字符串'hello'而非可调用对象,因此抛出TypeError: 'str' object is not callable

另外,wrapper_f在这里完全多余,它不仅没有任何实际作用,还破坏了add方法的正常执行流程——add方法本身就是一个返回装饰器的函数,不需要额外包装。

修复后的代码

直接移除多余的wrapper_f装饰器即可,同时优化类型注解以符合PEP8规范:

import typing as tp 

class A:
    def __init__(self, n: str):
        self.__n__ = n
        self.__dict_path__: dict[str, tp.Callable[[], str]] = {}
    
    def add(self, name: str) -> tp.Callable[[tp.Callable[[], str]], tp.Callable[[], str]]:
        def decorator(f: tp.Callable[[], str]) -> tp.Callable[[], str]:
            self.add_new(name, f)
            return f
        return decorator

    def add_new(self, name: str, f: tp.Callable[[], str]) -> None:
        self.__dict_path__[name] = f
   
    def get(self, name: str) -> str:
        return self.__dict_path__[name]()

k = A('Hallo')

@k.add('hello')
def help() -> str:
    return "Hello =)))"

if __name__ == "__main__":
    print(k.get('hello'))  # 输出: Hello =)))

额外说明

  • 类名遵循PEP8规范改为大驼峰式的A,类型注解更精确
  • add方法返回一个装饰器函数,该装饰器会将被装饰的函数注册到实例的__dict_path__字典中
  • 调用k.get('hello')时,会取出对应的函数并执行,返回预期的字符串

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 09:45:38