装饰器参数无法访问实例属性问题求解
问题解决:类装饰器访问实例属性报错的修复
问题原因
装饰器是在类定义阶段执行的,此时类还未实例化,self对象根本不存在,所以直接在装饰器参数里写self.logs或self.events必然触发NameError。核心错误在于试图在类加载阶段就访问只有实例化后才存在的属性。
解决方案
不要直接传递实例属性,而是传递属性名称的字符串,在装饰器内部通过实例对象(即方法里的self)动态获取对应的列表。同时调整装饰器的嵌套结构,使其符合类方法装饰器的正确逻辑。
修改后的完整代码
class MyMockClient: def __init__(self, logs, events): self.logs = logs self.events = events def __iterate_pushes(self, attr_name): """ 装饰器:循环调用被装饰方法,直到对应列表被完全弹出 """ def decorator(decorated_func): def wrapper(self): responses = [] # 通过属性名动态获取实例中的列表 target_list = getattr(self, attr_name) while len(target_list) > 0: response = decorated_func(self) responses.append(response) return responses return wrapper return decorator @__iterate_pushes("logs") def push_log(self): # 推送第一条日志并在成功后弹出 log = self.logs[0] print(log, "some extra logics for logs") response = "OK" # 假设API调用成功 if response == "OK": self.logs.pop(0) return response @__iterate_pushes("events") def push_event(self): # 推送第一条事件并在成功后弹出 event = self.events[0] print(event, "some extra logics for events") response = "OK" # 假设API调用成功 if response == "OK": self.events.pop(0) return response my_mock_client = MyMockClient( logs = [1, 2, 3], events = [4, 5, 6] ) # 测试调用 print(my_mock_client.push_log()) print(my_mock_client.push_event())
关键修改点
- 装饰器参数改为属性名字符串:把
@__iterate_pushes(obj = self.logs)改成@__iterate_pushes("logs"),类定义阶段仅传递字符串,避免访问不存在的self。 - 装饰器内部动态获取属性:在包装函数
wrapper里,通过getattr(self, attr_name)获取实例对应的列表,此时self是已实例化的对象,属性已存在。 - 修正装饰器嵌套结构:移除原代码中多余的
outer_wrapper层,调整为标准的带参数装饰器结构:参数→装饰器→包装函数。
运行结果
执行代码后会依次打印每条日志和事件的处理信息,最终返回["OK", "OK", "OK"],说明所有元素都被成功推送并弹出。
内容的提问来源于stack exchange,提问作者Seymour
相关产品推荐
相关产品推荐

