013、Python数据结构入门:字典(Dictionary)的妙用
·
013、Python数据结构入门:字典(Dictionary)的妙用
昨天调一个嵌入式日志解析脚本,同事传过来一段文本配置,要快速匹配每个设备ID对应的校准参数。他用了两个并行的列表,靠下标来对齐数据,结果设备顺序一变,整个映射全乱套了。我指着屏幕说:“这个场景,就该用字典。”
字典是什么?键值对的工具箱
字典在Python里用花括号{}表示,每个元素是一个键:值对。它不像列表靠位置索引,而是用唯一的键来存取值。你可以把它想象成一本通讯录——通过名字(键)快速找到电话(值),而不需要记住这个人排在第几位。
# 坏味道的写法:用两个列表维护映射关系
device_ids = ["SN001", "SN002", "SN003"]
cal_params = [1.23, 4.56, 7.89]
# 一旦设备顺序打乱,对应关系就崩了
# 这才是正解
device_calibrations = {
"SN001": 1.23,
"SN002": 4.56,
"SN003": 7.89
}
# 不管数据怎么排列,通过SN002总能拿到4.56
几个真实场景下的字典操作
嵌入式开发里经常遇到配置表解析。比如从芯片datasheet里抄出一堆寄存器地址和默认值:
# 寄存器地址映射表
register_map = {
0x00: "控制寄存器",
0x04: "状态寄存器",
0x08: "数据缓冲区",
0x0C: "中断使能"
}
# 查寄存器用途
addr = 0x08
print(f"地址{hex(addr)}是{register_map.get(addr, '保留寄存器')}")
# get()比直接写register_map[addr]安全,找不到键时返回默认值而不是报错
调试时经常要统计各种事件次数,字典的defaultdict能省不少事:
from collections import defaultdict
# 传统写法要判断键是否存在
error_counts = {}
for error_code in log_messages:
if error_code in error_counts:
error_counts[error_code] += 1
else:
error_counts[error_code] = 1
# 用defaultdict一行搞定
error_counts = defaultdict(int) # 默认值0
for error_code in log_messages:
error_counts[error_code] += 1 # 直接加,不存在的键会自动创建
踩过的坑和避坑指南
新手常犯的错误是拿可变对象当键。字典的键必须是不可变类型,字符串、数字、元组都可以,但列表不行:
# 这样写会直接报TypeError
bad_dict = {["配置组", "子项1"]: "参数值"}
# 改成元组就对了
good_dict = {("配置组", "子项1"): "参数值"}
另一个坑是遍历时修改字典。Python不允许在遍历过程中增删键:
config = {"a": 1, "b": 2, "c": 3}
# 危险操作:遍历时删除
for key in config:
if key == "b":
del config[key] # RuntimeError在这等着你
# 安全做法:先记录要删的键
to_delete = []
for key in config:
if key == "b":
to_delete.append(key)
for key in to_delete:
del config[key]
字典推导式:优雅的初始化技巧
处理硬件采集的数据时,经常需要快速转换格式。比如把ADC通道列表转成通道-数据的映射:
channels = ["AIN0", "AIN1", "AIN2", "AIN3"]
raw_values = [1023, 2047, 3071, 4095]
# 传统写法
channel_data = {}
for i in range(len(channels)):
channel_data[channels[i]] = raw_values[i]
# 字典推导式更清爽
channel_data = {ch: val for ch, val in zip(channels, raw_values)}
# 还能加条件过滤
valid_data = {ch: val for ch, val in channel_data.items() if val > 1000}
个人经验:什么时候该用字典?
做了这么多年底层开发,我的经验是:但凡需要“查表”的地方,字典都是首选。硬件寄存器映射、协议字段解析、设备ID管理、状态机转换表——这些场景字典都比列表更合适。
但要注意内存开销。嵌入式环境资源紧张时,如果键的数量固定且不多,用元组列表可能更省内存。不过大多数情况下,字典的可读性和效率优势更值得考虑。
最后给个实用建议:调试时多用pprint打印字典,层次结构一目了然:
from pprint import pprint
complex_config = {
"device": {"id": "SN001", "type": "sensor"},
"params": {"sampling_rate": 1000, "range": "±10V"},
"calibration": {"offset": 0.001, "gain": 0.998}
}
pprint(complex_config, indent=2) # 比print()清晰多了
字典不是万能的,但确实是Python里最实用的工具之一。把它放进你的工具箱,下次遇到映射关系的问题,就不会再想着用两个列表硬凑了。
更多推荐


所有评论(0)