文章目录
【Python每日小技巧】别再踩坑!5种姿势教你优雅地修改字典值
前言
在 Python 里,字典(dict)堪称“瑞士军刀”,但不少初学者(甚至老鸟)都会在“如何正确修改值”这件事上翻车:
KeyError直接劝退?- 想把值加 1 结果把整个列表给覆盖了?
- 想批量改值却写了三层
for循环?
今天这篇文章,就把我踩过的坑一次性打包给你,带你从“修字典”进化到“优雅地修字典”。读完你可以直接收藏当 cheat-sheet 用!
1. 直接赋值:最基础,也最危险
user = {"name": "Alice", "age": 25}
user["age"] = 26 # 存在就覆盖
user["city"] = "Shanghai" # 不存在就新建
⚠️ 注意:如果键不存在,会直接新增,而非报错。
很多 bug 就是因为“以为会报错,结果悄悄插进去了”。
2. 先查后改:防御式写法
if "age" in user:
user["age"] += 1
else:
print("age 不存在,跳过")
优点:安全。
缺点:两行起步,代码膨胀。
3. dict.get + 赋回:一行解决“不存在就跳过”
user["age"] = user.get("age", 0) + 1
利用 get 给默认值,再写回。
小技巧:对计数器、累加器特别香。
4. setdefault:初始化 + 修改二合一
# 统计字符出现次数
from collections import defaultdict
counter = {}
for ch in "abracadabra":
counter[ch] = counter.setdefault(ch, 0) + 1
print(counter)
# {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
setdefault 在键不存在时先插入默认值,再返回该值,省去一次 if。
如果你还没用过,强烈建议试试!
5. 批量修改:字典推导式 & update
5.1 字典推导式(推荐)
prices = {"apple": 8, "banana": 5, "pear": 6}
# 全场 9 折
prices = {k: v * 0.9 for k, v in prices.items()}
一行完成映射,可读性高。
5.2 update + 字典推导式
prices.update({k: v * 0.9 for k, v in prices.items()})
当原字典被多处引用,不想重新绑定变量名时用 update。
6. 嵌套字典怎么办?——一行代码“点”进去改
data = {"user": {"profile": {"age": 25}}}
# 想给 age + 1
from functools import reduce
import operator
def nested_set(dic, keys, value):
reduce(operator.getitem, keys[:-1], dic)[keys[-1]] = value
nested_set(data, ["user", "profile", "age"], data["user"]["profile"]["age"] + 1)
print(data)
# {'user': {'profile': {'age': 26}}}
如果你经常操作 MongoDB 或 JSON 配置,这招能救命。
7. 性能对比小实验
随手跑个 timeit,看看谁更猛:
| 方法 | 100万次耗时 |
|---|---|
if key in dict | 0.45 s |
get + 赋值 | 0.42 s |
setdefault | 0.48 s |
结论:差距微乎其微,可读性优先!
8. 常见错误 Top3
-
误用
dict[key]++
Python 没有++,请用dict[key] += 1。 -
遍历中直接修改尺寸
for k in d: if some_condition(k): del d[k] # RuntimeError: dictionary changed size during iteration正确姿势:先收集要删的键,再批量
del。 -
把可变对象当默认值
def func(d={}): ...默认字典会跨调用共享,踩一次坑记一辈子。
9. 总结速查表
| 场景 | 推荐写法 |
|---|---|
| 键一定存在 | d[k] = new_v |
| 键可能不存在,需默认值 | d[k] = d.get(k, default) + delta |
| 初始化并修改 | d[k] = d.setdefault(k, 0) + 1 |
| 批量映射 | {k: f(v) for k, v in d.items()} |
| 嵌套结构 | reduce + getitem 或 dpath 库 |
10. 彩蛋:Python 3.9+ 新语法
合并两个字典只需 |:
defaults = {"host": "localhost", "port": 3306}
custom = {"port": 5432}
config = defaults | custom # {'host': 'localhost', 'port': 5432}

被折叠的 条评论
为什么被折叠?



