如何从静态方法的装饰器中获取类名?解决AttributeError报错
如何从静态方法的装饰器中获取类名?
问题重现
使用自定义缓存装饰器CachedStaticMethod装饰静态方法时,抛出如下错误:
AttributeError: 'staticmethod' object has no attribute 'qualname'
原因是装饰器接收的是staticmethod对象而非原始函数,该对象没有__qualname__属性,导致无法获取静态方法所属的类名。
解决方案
核心思路是利用描述器的__get__方法获取类对象(owner参数)并保存类名;同时通过staticmethod的__func__属性访问原始函数的信息,另外修正代码中的语法错误。
修正后的完整代码
import os import pickle import hashlib def read_file(path): # 实现文件读取逻辑 with open(path, 'rb') as f: return f.read() def write_file(path, content): # 实现文件写入逻辑 os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'wb') as f: f.write(content) class CachedStaticMethod: path = "cache" def __init__(self, func): self.func = func self.class_name = None # 用于存储类名 def __get__(self, instance, owner): if owner is not None: self.class_name = owner.__name__ # 获取并保存类名 if instance is None: return self return self.func.__get__(instance, owner) def __call__(self, *args, **kwargs): cache_path = self.__get_path(*args, **kwargs) try: content = read_file(cache_path) result = pickle.loads(content) except Exception as e: # 调用静态方法包装的原始函数 result = self.func.__func__(*args, **kwargs) content = pickle.dumps(result) write_file(cache_path, content) return result def __get_path(self, *args, **kwargs): class_name = self.class_name # 通过__func__获取原始函数名称 function_name = self.func.__func__.__name__ # 修正编码语法错误 hash_input = f"{class_name}.{function_name}({args}, {kwargs})".encode("utf-8") hash_value = hashlib.md5(hash_input).hexdigest() filename = f"{hash_value}.cache" return os.path.join(self.path, filename) class MyClass: @CachedStaticMethod @staticmethod def my_static_method(param1: int, param2: str) -> float: """ This is a cached static method of MyClass. """ result = 3.14 * param1 + len(param2) return result # 测试 result1 = MyClass.my_static_method(5, "hello") result2 = MyClass.my_static_method(5, "hello") # 第二次调用将使用缓存 print(result1) print(result2)
关键改动说明
- 保存类名:在
__get__方法中,通过owner.__name__直接获取类名并存储,后续生成缓存路径时直接调用。 - 访问原始函数:
staticmethod对象的__func__属性指向被包装的原始函数,通过它可以获取函数名并执行实际逻辑。 - 修复语法错误:将原代码中错误的
hash_input编码方式修正为.encode("utf-8")。 - 完善文件操作:补充了
read_file和write_file的实际实现,确保缓存功能可以正常运行。
内容的提问来源于stack exchange,提问作者user1633272
相关产品推荐
相关产品推荐

