跳转至

P2-8.3 字典(dictionary):按键(key)查找值的结构

Section ID: P2-8.3 Version: v2026.07.20

在 P2-8.2 中,我们看过了有顺序的值集合,也就是列表(list)。但并不是所有数据都只靠顺序来读取。

在按设置名称查设置值、按标签编号查标签名称、按用户 ID 查用户信息这类场景中,比起位置,更重要的是名字标签。在 Python 中,这种结构通过字典(dictionary)来处理。

这里会说明 字典(dictionary)键(key) 的基本区分。关于 列表(list) 与按顺序访问的代表性说明放在 P2-8.2,关于 值(value)类型(type) 的代表性说明放在 P2-8.1 和 概念词典。这里集中处理的是:应该按什么标准去查找值?

如果前一节里的列表是围绕 它是第几个值? 来读,那么这里的中心就是 它是通过什么名字或标识符来查找? 只要先抓住这个差异,后面即使在同一个循环里同时遍历列表和字典,也更容易区分 到底是按什么标准取出来的?

本节要先抓住什么 紧接着会出现什么问题 之后会在什么地方再次使用
字典是按键查值的结构 这会接到 P2-8.4 中“列表和字典如何通过迭代来遍历”。 之后在读取配置值、JSON 响应、元数据、评估结果时会反复出现。
列表与字典的差异,本质上是位置和键的差异 这会接到判断“哪种数据更适合哪种结构”的标准。 之后会在 DataFrame 列、标签映射、API 响应解释里再次使用。
dict[key]get() 在失败处理上不同 这会接到“当键可能不存在时,应该怎样处理输入”。 之后在预处理、预测结果解析、外部响应检查中都很重要。
术语 本节先要抓住的意思
字典(dictionary) 把键和对应值连接起来的映射结构。
键(key) 用来查找值的标准名称或标识符。
值(value) 与键连接在一起的真实数据。
映射(mapping) 把某个标准连接到某个对象上的结构。
get() 在键可能不存在的情况下,让读取方式更安全一点的访问方式。

核心判断标准:字典(dictionary):按键(key)查找值的结构

  • 能把字典(dictionary)解释为键(key)和值(value)的集合。
  • 能把字典解释为通用映射(mapping)结构。
  • 能把列表与字典的差异解释成位置(index)和键(key)的差异。
  • 能说明 dict[key]dict.get(key) 的区别。
  • 能读懂配置值、标签映射、样本 ID 查询、列说明等例子。

三个标准

这里先看的不是语法,而是 应该按什么标准去查值? 下面三个标准会成为后面阅读迭代和缺失键处理说明时的基础。

标准 为什么重要 本节所需的理解程度
字典是按键查值的结构 它能最快帮助你抓住与列表的区别 理解这是一个按名字标签或标识符来查找,而不是按位置来查找的结构
键和值分别是查找标准与被连接的内容 它能让配置值、标签映射和 ID 查询都被读成同一种结构 能说明成:用 "score" 去找到分数,用 0 去找到标签名称
初学时先把字典理解成映射会更安全 这样不容易一开始就被实现术语 hash map 困住 在读代码阶段,先把它看成把键连接到值上的结构

字典是按标准查找值的结构

一般来说,映射(mapping)就是把某个标准连接到某个值上的结构。这个标准可以叫键(key),而连接到键上的对象可以叫值(value)。

在 Python 中,这种映射结构通常通过字典(dictionary)来表达。

问题场景:我想先看一个最简单的字典例子,通过名字标签来找到值。 输入(input):含有 namescorepassed 这些键的 student 字典。 期望输出(output):会打印 student["name"]student["score"] 的值。 要确认的概念:字典不是按位置,而是按键来查值的映射结构。

1
2
3
4
5
6
7
8
9
# 这个例子用来确认字典如何通过键查找并连接值。
student = {
    "name": "Kim",
    "score": 82.5,
    "passed": True,
}

print(student["name"])
print(student["score"])

如果列表是按位置查值,那么 Python 字典就是按键查值。

结构 查值的标准 例子
列表(list) 位置(index) scores[0]
字典(dictionary) 键(key) student["score"]

在 AI 实践里,经常会看到字典。

  • 配置值集合:{"learning_rate": 0.01, "epochs": 10}
  • 一行数据:{"text": "hello", "label": "positive"}
  • API 响应的一部分:{"model": "example", "tokens": 120}
  • 模型评估结果:{"accuracy": 0.91, "loss": 0.32}

当重要的不是“按顺序是第几个值”,而是“它是哪个名字对应的值”时,就使用字典。

视角 一般说明 在 Python 中
映射(mapping) 把某个标准连接到某个值上的结构 使用字典(dictionary)
键(key) 查找值的标准 可以是字符串、数字等可哈希(hashable)的值
值(value) 与键连接的对象 可以是数字、字符串、列表、字典等多种值

字典经常被当作通用 map 结构来使用

字典并不只是把多个值集中放在一个地方的语法。Python 官方文档把字典描述为映射类型(mapping type)。所谓映射(mapping),就是把某个键(key)连接到某个值(value)的结构。这个说明不仅适用于 Python,在读取配置文件、JSON 响应、标签映射和元数据时也一样成立。

在这一节里,用下面这个标准来理解字典。

字典就是一种通用 map:给它一个键,就能找到连接着的值。

问题场景:我想看一个最小的对应表,把数字标签改成人能读懂的名字。 输入(input):把 01 连接到字符串标签上的字典 label_name,以及预测值 1。 期望输出(output):会打印与预测值 1 对应的 "positive"。 要确认的概念:只要给出标准键,字典就能直接取出连接的值。

1
2
3
4
5
6
7
8
# 这个例子用来确认字典如何通过键查找并连接值。
label_name = {
    0: "negative",
    1: "positive",
}

prediction = 1
print(label_name[prediction])

在这个例子里,如果 prediction1,字典就会找到和键 1 相连的 "positive"。与其像列表那样让人去想“应该查第几个格子”,这里是直接按键取值。

这种感觉在实际工作和 AI 实践中会经常出现。

情况 按字典来看的方式
把标签编号改成人能读的名字 {0: "negative", 1: "positive"}
通过设置名称查设置值 {"batch_size": 32, "learning_rate": 0.001}
通过用户 ID 查用户信息 {"u001": {"name": "Kim"}}
通过列名查数据含义 {"score": "考试分数", "label": "正确标签"}

字典之所以让人感觉像通用 map,就是因为这些场景:如果键存在,就能马上取出值;如果键不存在,也能确认它不存在。

问题场景:我想确认一种基本模式:只有当设置名称存在于字典中时,才把值取出来。 输入(input):配置字典 config 和待查找的键 learning_rate。 期望输出(output):如果键存在,就会打印对应的设置值。 要确认的概念:字典可以先检查键是否存在,再更安全地取出值。

# 这个例子用来确认字典如何通过键查找并连接值。
config = {
    "batch_size": 32,
    "learning_rate": 0.001,
    "epochs": 10,
}

name = "learning_rate"

if name in config:
    print(config[name])

不过,谈到性能时要小心。字典通常是一种对键查询很有用、很快的结构,但这并不表示它在所有场景里都永远是最优选择。键必须是可哈希(hashable)的,而如果问题本身更重视数据顺序,那么列表或其他结构可能更合适。

字典是 hash map 吗?

看到 Python 字典时,自然会冒出一个问题:它是不是 hash map? 简短地回答是:从使用角度看,可以把字典理解成按键查值的映射(mapping)结构;从实现角度看,也可以把它理解成利用哈希(hash)的数据结构。

但在本节中,我们不会马上只把字典叫作 hash map。原因有三点。

第一,Python 官方文档把字典说明为标准映射类型(mapping type)。读者首先需要熟悉的视角是:它把键连接到值上。

第二,hash map 这个词更接近实现方式。它会连带出 hash、hashable、collision、table 这些细节概念。而本节的目的,是在阅读 Python 代码时理解 为什么不是按位置,而是按键查找?,而不是先钻进内部实现。

第三,Python 字典并不能直接等同于 C++ STL 里的某一种命名容器。如果把它理解成像 C++ std::map 那样按键排序的结构,会有偏差;如果把它理解成像 multi-index 那样可以同时用多个索引查询同一份数据的结构,也过头了。Python 官方文档说明,字典键会保留插入顺序(insertion order),但这并不表示它会按键排序。

即便如此,和哈希的联系仍然值得记住。Python 字典的键必须是可哈希(hashable)的。因此,字符串、数字、元组这类不会变化的值经常用作键,而像列表这样可变的值通常不能作为字典键。

问题场景:我想看一个最简单的字典例子:通过字符串键来找分数。 输入(input):scores_by_name,其中名字是键,分数是值。 期望输出(output):会输出和键 "Kim" 对应的分数 82。 要确认的概念:字典查询是通过稳定的键来找到值的动作。

1
2
3
4
5
6
7
# 这个例子用来确认字典如何通过键查找并连接值。
scores_by_name = {
    "Kim": 82,
    "Lee": 91,
}

print(scores_by_name["Kim"])

在这个例子里,"Kim" 是键,而 Python 会用这个键去找到连接的值。即使不完全理解内部实现,也要留下这种感觉:如果要按键查值,这个键就必须能稳定地标识它。

问题 本节中的回答
字典是 hash map 吗? 从实现角度可以理解成基于哈希的映射结构。
那是不是只要记成 hash map 就行? 初期更安全的做法,是先把它理解成 按键查值的映射
它会像 map tree 那样排序吗? 按官方文档,它保留插入顺序,但不把它解释为按键排序结构。
它是 multi-index 结构吗? 不是。一个字典就是通过一个键查一个值的映射。如果需要多个查询标准,就要另外设计结构。
为什么键会有限制? 因为键是查值标准,所以必须是可哈希(hashable)的。
现在需要学习哈希表吗? 这一节不需要。以后讲数据结构时再深入。

还有一点要注意:同一个键不能存多次。如果在同一个键下面存入新值,旧值就会被新值覆盖。

问题场景:我想确认同一个键赋值两次时,最后只会留下最后那个值。 输入(input):空字典 scores,以及对键 "Kim" 的两次赋值。 期望输出(output):字典中 "Kim" 键下面只剩下最后的值 91。 要确认的概念:一个键只指向一个当前值,重新赋值时旧值会被覆盖。

1
2
3
4
5
6
7
# 这个例子用来确认字典如何通过键查找并连接值。
scores = {}

scores["Kim"] = 82
scores["Kim"] = 91

print(scores)

这段代码不会在 "Kim" 这个键下面保存两个分数。只会留下最后的值 91。如果想在一个键下面收集多个值,就必须在值(value)那一侧放入列表。

问题场景:我想看看怎样把一个人的多个分数放在同一个键下面保存。 输入(input):一个字典,其中键 "Kim" 对应分数列表 [82, 91]。 期望输出(output):打印 "Kim" 键下的分数列表。 要确认的概念:如果一个键下需要多个值,就要在值一侧放入像列表这样的集合结构。

1
2
3
4
5
6
# 这个例子用来确认字典如何通过键查找并连接值。
scores = {
    "Kim": [82, 91],
}

print(scores["Kim"])

因此,Python 字典虽然会给人一种 按键访问很快、很方便 的感觉,但它并不是面向大规模数据的万能索引结构。如果数据非常大、需要同时按多个标准查找,或者排序与范围搜索更重要,就应该考虑数据库、pandas 或其他索引结构。本节只处理这之前的阶段:建立在 Python 代码中最常遇到的那种按键映射感觉。

这里记住下面这些标准。

  • 当顺序和位置重要时,使用列表。
  • 当按键查值更重要时,使用字典。
  • 字典适合用来表示配置值、标签映射、元数据这类“按名字查找的数据”。
  • 字典虽然和哈希实现有关,但本节先从映射(mapping)角度来读。
  • 不要把字典直接定性成键排序树或 multi-index 结构。
  • 像“按键计数”这样边循环边往字典里累积值的模式,会在 P2-8.4 中处理。

使用字典的场景

按什么标准去查值? 已经很明确时,字典就很合适。

配置值集合

问题场景:我想看一个典型的字典用法:通过设置名称查训练配置值。 输入(input):包含 batch_sizelearning_rateepochsconfig。 期望输出(output):会输出 learning_rate 的值。 要确认的概念:配置数据更重视名字而不是顺序,因此和字典很匹配。

1
2
3
4
5
6
7
8
# 这个例子用来确认字典如何通过键查找并连接值。
config = {
    "batch_size": 32,
    "learning_rate": 0.001,
    "epochs": 10,
}

print(config["learning_rate"])

对配置值来说,比起顺序,更重要的是名字。通过 learning_rate 这个名字来查值,比像 config[1] 那样按位置查,意义更清楚。

把标签编号改成人能读的名字

问题场景:我想看一个例子,把模型输出的数字标签改成可读的字符串名字。 输入(input):连接数字键和情感名称的 label_map,以及预测标签 2。 期望输出(output):打印字符串 neutral。 要确认的概念:字典经常被当作标签编号和标签名称之间的对照表。

# 这个例子用来确认字典如何通过键查找并连接值。
label_map = {
    0: "negative",
    1: "positive",
    2: "neutral",
}

predicted_label = 2

print(label_map[predicted_label])

当模型输出是数字标签时,可以使用字典把它转成人类可读的名称。

通过样本 ID 查找数据

问题场景:我想看一种结构:通过一个样本 ID,马上找到对应数据的文本。 输入(input):samples_by_id,其中样本 ID 是键,样本信息是值。 期望输出(output):打印 "s001" 对应的文本 "good product"。 要确认的概念:字典可以用作从标识符直达数据正文的查询结构。

1
2
3
4
5
6
7
8
9
# 这个例子用来确认字典如何通过键查找并连接值。
samples_by_id = {
    "s001": {"text": "good product", "label": "positive"},
    "s002": {"text": "bad service", "label": "negative"},
}

sample_id = "s001"

print(samples_by_id[sample_id]["text"])

当数据变多时,比起“它是第几个数据”,更重要的可能是“它是哪个 ID 的数据”。这时字典就像一张从 ID 通往样本的映射表。

通过列名附加意义

问题场景:我想看一个例子:把列名代表什么含义,另外用一张说明表管理起来。 输入(input):column_description,把列名连接到说明字符串上。 期望输出(output):打印键 "score" 的说明。 要确认的概念:字典很适合按名字整理元数据和说明信息。

1
2
3
4
5
6
7
8
# 这个例子用来确认字典如何通过键查找并连接值。
column_description = {
    "text": "输入句子",
    "label": "正确标签",
    "score": "模型分数",
}

print(column_description["score"])

在读取数据集时,如果把列名的意义另外整理起来,后面的预处理和文档化会轻松很多。

字典看起来像 object,但并不是同一个词

由于前面的这些例子,字典看起来可能很像 JSON 中的 object,或者某些语言里的 object 表达。它们都使用花括号,也都按名字来查值。所以在看 API 响应或配置文件时,字典和 object 可能会出现相似的外形。

但在本节中,我们不会把字典叫成 object。因为在 Python 中,object 是一个更大的词。数字、字符串、列表、字典、函数都可以视作 object。而字典只是这些对象之中的一种:它是把键(key)连接到值(value)上的映射(mapping)结构。

视角 Python 字典(dictionary) 一般 object 视角
核心想法 通过键查值的映射(mapping) 同时拥有状态和行为的对象
查值标准 键(key) 属性(attribute)、字段(field)
AI 实践连接 配置值、标签映射、API 响应、元数据 类实例、模型对象、库对象
注意点 键不存在时可能报错 不同对象的访问方式可能不同

因此,把字典先读成“按键查值的结构”,而不是“轻量对象”,误解会更少。至于 object、class、method 这些内容,已经超出本章中心范围,会在以后需要时单独处理。

要小心键可能不存在

如果直接从字典里取一个不存在的键,就可能报错。

问题场景:我想展示当直接查一个不存在的键时,会有什么风险。 输入(input):只包含 namescore 的字典 student,以及不存在的键 "label"。 期望输出(output):展示查询不存在的键时失败的例子。 要确认的概念:如果默认认为字典里的所有键始终都存在,就可能报错。

1
2
3
4
# 这个例子用来确认字典如何通过键查找并连接值。
student = {"name": "Kim", "score": 82.5}

print(student["label"])

因为 "label" 这个键不存在,所以这段代码会失败。

当键可能不存在时,可以使用 get()

问题场景:我想确认一种更安全一点的方式来读取不存在的键。 输入(input):student.get("label")student.get("label", "unknown")。 期望输出(output):默认会得到 None;如果给定默认值,则会输出 "unknown"。 要确认的概念:当处理键可能缺失的数据时,get() 是一种更安全的查询工具。

1
2
3
4
5
# 这个例子用来确认字典如何通过键查找并连接值。
student = {"name": "Kim", "score": 82.5}

print(student.get("label"))
print(student.get("label", "unknown"))

当处理数据文件或 API 响应时,如果假定所有键一定都存在,就容易出问题。真实数据里可能会混有缺失值、不同名称的值,或者与预期不同的类型。

用案例来看

案例 1. 当你想把标签编号改成人能读的名字时

假设一个情感分类模型的预测结果只返回 012 这样的数字。人看到这些数字,很难立刻理解它们的意义,而在报告或界面上,需要的是 negativepositiveneutral 这种名字。

这时最先想到的方法,也许是把它们按顺序放进列表里。但这里真正重要的并不是“它是第几个值”,而是 哪个编号对应哪个名字。也就是说,比起位置,更重要的是标准键。

字典正是适合读取和书写这种对照表的结构。只要像 0 -> negative1 -> positive 这样把键和值连接起来,就能很容易把预测数字改成人能读懂的名字。配置值、样本 ID、列说明也都可以用同样方式来看。

可确认的结果,就是把预测标签数字放进去之后,是否能立刻得到名字。如果通过 label_map[prediction] 就能得到想要的字符串,那么这个问题就比起列表,更自然地应该用字典来读。

检查清单

  • 能把字典(dictionary)解释成键和值的集合。
  • 能把字典解释成映射(mapping)结构。
  • 能从使用角度把字典解释为映射,从实现角度解释为基于哈希的结构。
  • 能说明列表按位置查值,而字典按键查值。
  • 能说明 get() 在键可能不存在的情况下很有用。
  • 能读懂标签映射、配置值、样本 ID 查询、列说明这些例子。
  • 能区分在键可能不存在时应该怎样选择读取方式。

来源与参考资料

  • Python Software Foundation, Data Structures, Python 3.14.6 documentation,确认日期:2026-07-20。用于确认字典创建、通过 key 访问 value,以及使用 items() 遍历的示例。
  • Python Software Foundation, Mapping Types — dict, Python 3.14.6 documentation,确认日期:2026-07-20。用于确认 dict 是 mutable mapping type,并且是通过 key 查找 value 的结构。
  • Python Software Foundation, Glossary: dictionary, hashable, Python 3.14.6 documentation,确认日期:2026-07-20。用于确认 dictionary 与 hashable 的术语定义。
  • Python Software Foundation, Data model, Python 3.14.6 documentation,确认日期:2026-07-20。用于确认对象的 identity/type/value 和 hashability,作为字典 key 限制的背景依据。