跳到主要内容

Python 字典与键值状态

dict 将唯一且可哈希的键(Key)映射到值(Value)。它是可变的,并严格保持插入顺序,但请注意:插入顺序不等于排序顺序。

counts = {"jpg": 10, "csv": 2}
counts["csv"] += 1
counts["txt"] = 4

查找策略

根据业务对“键缺失”的处理需求,选择合适的方法:

required = config["region"] # 键缺失时抛出 KeyError
optional = config.get("timeout", 30) # 键缺失时返回默认值 30

if "token" in config: # 成员检查仅针对键
use(config["token"])

注意get 方法无法区分“键不存在”和“键存在但值恰好等于默认值”这两种情况。如果业务逻辑需要严格区分,请使用 in 进行成员测试,或定义一个私有的哨兵值(Sentinel)。

对于累加场景,collections.defaultdictcollections.Counter 通常比反复调用 setdefault 更能清晰表达意图。

键与哈希

键必须是可哈希的。字符串、数字以及由可哈希元素组成的元组通常符合要求;列表和字典则不行。

核心规则:

  1. 比较相等的对象必须具有相同的哈希值。
  2. 一旦对象被用作键,若修改了参与相等性或哈希计算的数据,会导致映射在逻辑上不一致(例如找不到原本存在的键)。

最佳实践:优先使用具有稳定相等语义的领域标识符作为键。不要仅仅因为可以自定义哈希实现,就将可变容器用作键。

迭代与视图

for key in mapping:
...

for key, value in mapping.items():
...

keys = mapping.keys() # 动态视图,非列表副本
values = mapping.values()

警告:在遍历视图期间改变字典的大小(增删键值对),可能会引发错误或导致部分数据被跳过。如果需要基于当前状态的快照进行遍历,请先转换为列表:list(mapping.items())

更新与合并

  • update 方法会直接修改原字典(接收者)。
  • | 运算符会创建一个新字典。

在两种情况下,当键重叠时,右侧的值会覆盖左侧的值。

effective = defaults | overrides
defaults.update(overrides)

浅层合并:上述操作均为浅层合并。嵌套的映射(如字典中的字典)会被整体替换,而不会递归合并内部结构。对于深层配置合并,需定义明确的策略。

性能成本

  • 对于 CPython 的哈希表实现,假定哈希与相等性检查为常数时间,查找、插入、删除的平均时间复杂度为 O(1)O(1),但这并非最坏情况下的常数时间保证。
  • 迭代的时间复杂度为 O(n)O(n)

相等的键、顺序与独立默认值

映射契约从 Python 3.7 起保证插入顺序。更新值不会移动键,删除再插入则会把键放到末尾。字典相等性比较键值对,不比较插入顺序。11.0True 这样的相等数值键访问同一个条目。

mapping = {1: "integer", True: "boolean", 1.0: "float"}
assert len(mapping) == 1
assert mapping[1] == "float"
ordered = {"a": 1, "b": 2}
ordered["a"] = 3
assert list(ordered) == ["a", "b"]
assert ordered.pop("a") == 3
ordered["a"] = 4
assert list(ordered) == ["b", "a"]
assert ordered == {"a": 4, "b": 2}

shared = dict.fromkeys(["a", "b"], [])
shared["a"].append(1)
assert shared["b"] == [1]
separate = {key: [] for key in ["a", "b"]}
separate["a"].append(1)
assert separate["b"] == []

fromkeys 为每个键复用同一个传入值;推导式则为每个条目计算一次值表达式。对象的哈希值必须在其生命周期内保持稳定。哈希相同不代表键相等,发生碰撞时还需要相等性检查。包含列表的元组不可哈希。键不存在时,del mapping[key]pop(key) 抛出 KeyErrorpop(key, default) 则返回默认值。与 get 一样,默认值表达式在方法调用前就会求值,即使键已经存在。

参考来源

探索关联打开关联网络