Python函数操作外部变量报UnboundLocalError的规范解法
报错根因
Python的作用域规则是:只要函数内部存在对某个变量的赋值操作,解释器就会默认将该变量标记为函数局部变量,不会去全局作用域查找同名变量。
你的代码中在if分支内存在newdict = dict(response_json)的赋值语句,因此newdict被判定为trades()函数的局部变量,但if判断条件中提前读取了newdict['id'],此时局部变量newdict还未完成赋值,就触发了UnboundLocalError。
关于
global写法的评价 在函数内加global newdict声明确实可以修复这个报错,语法完全合法,在几十行以内的临时小脚本里这么写不会有实质问题。但这种写法不符合高可维护性的编码规范:全局变量可以被任意位置的代码修改,随着代码量增长,很难追踪变量的修改路径,排查bug的成本会很高,不适合在正式项目里使用。
更合理的实现方案
推荐用类来封装需要持久保存的状态和对应的业务逻辑,完全不需要依赖全局变量,代码内聚性更强,后续扩展也更方便。
另外你的原代码还存在两个隐性bug,修复时一并处理:
- 原判断条件中
[elt['id'] for elt in response_json['data']]是列表类型,直接和整数类型的id值比较属于逻辑错误,Python3环境下会直接抛出类型不匹配的报错 - 原异常捕获逻辑没有指定捕获类型,且JSON解析失败后没有中断后续流程,会触发
response_json未定义的二次报错
修复后的完整参考代码:
import json import pprint import schedule import time from http import client class TradeDataFetcher: def __init__(self, trading_pair_id=48, limit=1): self.trading_pair_id = trading_pair_id self.offset = 0 self.limit = limit # 初始化存储最新交易数据,初始id设为0 self.latest_trade_info = {"id": 0} self.conn = client.HTTPSConnection("trade.blocktrade.com") def pull_latest_trades(self): # 构造请求拉取数据 req_path = f"/api/v1/trades/{self.trading_pair_id}?offset={self.offset}&limit={self.limit}" self.conn.request("GET", req_path, headers={"Content-Type": "application/json"}) resp = self.conn.getresponse() resp_raw = resp.read() # 解析响应,解析失败直接返回 try: resp_json = json.loads(resp_raw) except json.JSONDecodeError: print(f"响应解析失败,原始返回:{resp_raw}") return pprint.pprint(resp_json) # 提取最新交易id trade_id_list = [item["id"] for item in resp_json["data"]] print(f"拉取到的交易id列表:{trade_id_list}") current_latest_id = trade_id_list[0] # 比对id,有新数据则更新存储、执行业务逻辑 if current_latest_id > self.latest_trade_info["id"]: self.latest_trade_info = resp_json print("检测到新交易数据:") print(self.latest_trade_info) # 后续业务逻辑直接写在这里即可 if __name__ == "__main__": fetcher = TradeDataFetcher() schedule.every(5).seconds.do(fetcher.pull_latest_trades) while True: schedule.run_pending() time.sleep(1)
这种实现方式把所有和交易数据拉取、状态存储相关的逻辑都收敛在类内部,不会污染全局命名空间,后续要加功能(比如多交易对拉取、数据落盘、告警逻辑)只需要修改类内代码即可,维护成本低很多。
内容的提问来源于stack exchange,提问作者Valnurat
相关产品推荐
相关产品推荐

