如何访问被装饰类方法的self变量?优化JSON-RPC调用ID计数器递增实现方案
解决JSON-RPC ID计数器递增的问题
1. 如何访问被装饰类方法的self变量?
首先,你遇到的AttributeError: 'ServiceInterface' object has no attribute 'client_id'大概率是拼写笔误——你的代码里定义的是current_id,但报错信息里提到的是client_id,先检查代码里的变量名是否统一。
回到装饰器访问self的核心问题:类的实例方法被调用时,第一个参数必然是实例本身(也就是self),所以你的装饰器逻辑本身是可行的,但直接用args[0]不够直观,且依赖参数顺序,健壮性不足。更清晰的写法是在wrapper函数里直接把self作为第一个参数接收:
import functools def increment_id(func): @functools.wraps(func) def wrapper(self, *args, **kwargs): # 明确接收self参数 self.current_id += 1 return func(self, *args, **kwargs) return wrapper
这种写法完全符合Python类方法的调用逻辑,可读性更强,也避免了索引args可能带来的潜在问题。
2. 更优雅的JSON-RPC ID计数器实现方式
其实装饰器在这里属于“过度抽象”,因为ID递增的逻辑和create_payload方法强绑定——只有生成请求payload时才需要递增ID。直接把递增逻辑内嵌到create_payload里会更简洁直观:
import json import requests class ServiceInterface: def __init__(self, base_url): self.base_url = base_url self.headers = {"content-type": "application/json"} self.current_id = 0 def send(self, payload): """返回JSON-RPC请求的JSON字典。""" response = requests.request("POST", self.base_url, data=payload, headers=self.headers) if response.ok: return response.json() else: return {"error": {"code": response.status_code, "message": "HTTP Response Error"}} def create_payload(self, method, params): """创建JSON-RPC请求。""" self.current_id += 1 # 直接在生成payload前递增ID payload = { "jsonrpc": "2.0", "method": method, "id": self.current_id, "params": params, } return json.dumps(payload)
这种写法去掉了额外的装饰器嵌套,代码更易读,维护成本更低。
进阶:线程安全的ID计数器
如果你的代码会在多线程环境下运行,为了避免current_id递增时出现竞态条件,可以用threading.Lock来保护递增操作:
import threading class ServiceInterface: def __init__(self, base_url): self.base_url = base_url self.headers = {"content-type": "application/json"} self.current_id = 0 self.id_lock = threading.Lock() # 初始化锁 def create_payload(self, method, params): with self.id_lock: # 使用上下文管理器确保线程安全 self.current_id += 1 payload_id = self.current_id payload = { "jsonrpc": "2.0", "method": method, "id": payload_id, "params": params, } return json.dumps(payload)
测试代码验证
修正后的代码可以通过你的测试用例:第一次调用create_payload生成的ID为1,第二次为2,完全符合预期的断言逻辑。
内容的提问来源于stack exchange,提问作者Oddaspa
相关产品推荐
相关产品推荐

