- Python 字典 存储键和值对,并通过键快速查找值。
- 当某个键可能丢失时使用
get(),因为方括号会引发KeyError。 - 键必须是可散列的,例如字符串、数字或元组。列表不能是键。
copy()是浅层的,因此除非您使用deepcopy,否则嵌套数据将保持共享。
如果列表是一行编号的框,则 Python 字典 是一组带标签的框。您通过名称而不是位置来询问您想要的内容,这就是为什么字典位于 JSON 数据、配置、缓存和 Python 本身的大部分内容后面。
本教程从基础知识开始,然后介绍经验丰富的开发人员每天使用的模式。我们在 Python 3.13 上运行了所有示例,显示的输出来自该运行。
什么是字典?
字典或dict将键映射到值。每个键仅出现一次,值可以是任何内容,包括列表或其他字典。
| 类型 | 访问方式 | 已订购 | 重复项 | 最适合 |
|---|---|---|---|---|
清单 |
职位 | 是的 | 允许 | 序列 |
元组 |
职位 | 是的 | 允许 | 固定记录 |
设置 |
仅限会员 | 否 | 不允许 | 独特的物品 |
词典 |
钥匙 | 广告订单 | 钥匙是唯一的 | 按名称查找 |
从Python 3.7开始,字典正式保留插入顺序。许多较旧的教程仍然称它们为无序的,但这已不再正确。有关其他类型的更广泛比较,请参阅 Python 列表、元组和集合。
查找速度很快,因为字典使用哈希表。无论字典包含十个项目还是一百万个项目,检查键所花费的时间大致相同,而搜索列表会随着列表的增长而变慢。
创建字典
user = {"name": "Asha", "age": 31, "city": "Pune"}
empty = {}
from_keywords = dict(name="Asha", age=31)
from_pairs = dict([("a", 1), ("b", 2)])
大括号是最常见的形式。一个陷阱:{} 创建一个空字典,而不是一个空集合。对于空集,您需要 set()。
安全地读取值
有两种读取值的方法,当键可能不存在时,差异很重要:
user["name"] # 'Asha'
user["email"] # KeyError: 'email'
user.get("email") # None
user.get("email", "not set") # 'not set'
当密钥必须存在时使用方括号,这样丢失的密钥就会失败。当缺席属于正常情况时使用 get(),例如 API 响应中的可选字段。要检查键,请使用 in 运算符,它查看键而不是值:
"city" in user # True
"Pune" in user # False
添加、更新和删除
分配给一个键会更新它(如果存在),或者添加它(如果不存在):
user["age"] = 32
user["email"] = "asha@example.com"
print(user)
# {'name': 'Asha', 'age': 32, 'city': 'Pune', 'email': 'asha@example.com'}
Python 提供了多种删除项目的方法:
user.pop("city") # returns 'Pune' and removes it
user.pop("phone", None) # no error if it is missing
del user["email"] # removes it, and raises KeyError if missing
user.clear() # empties the dictionary
当您想要返回该值时,请使用 pop()。传递默认值作为第二个参数可以避免当密钥不存在时出现错误。 popitem() 删除并返回最近添加的对。
循环字典
循环直接给你钥匙。要获取键和值,请使用 items():
user = {"name": "Asha", "age": 32}
for key, value in user.items():
print(key, "=", value)
# name = Asha
# age = 32
keys()、values() 和 items() 返回实时视图而不是副本,因此它们反映了后来的更改。在循环字典时不要添加或删除键,因为 Python 会引发 RuntimeError。如果需要的话,请循环list(user)。
提示: in 对字典的检查速度很快,但 "Pune" in user.values() 必须扫描每个值。如果您经常对大数据执行此操作,则您的字典可能会以错误的方式键入。
字典方法备忘单
| 方法 | 它的作用 |
|---|---|
获取(k,默认) |
返回一个值,如果缺少键则返回默认值 |
keys() |
返回键的视图 |
values() |
返回值的视图 |
items() |
返回键和值对的视图 |
update(other) |
添加或覆盖另一个字典 |
弹出(k,默认) |
删除键并返回其值 |
popitem() |
删除并返回最后添加的对 |
设置默认值(k,v) |
返回值,如果key缺失则先插入v |
copy() |
返回浅拷贝 |
clear() |
删除所有内容 |
dict.fromkeys(keys, v) |
从键列表构建字典 |
合并字典
一个常见的需求是在默认值之上应用用户设置。当按键发生冲突时,右侧获胜:
defaults = {"theme": "light", "lang": "en"}
saved = {"theme": "dark"}
defaults | saved
{**defaults, **saved}
# Both give: {'theme': 'dark', 'lang': 'en'}
| 运算符需要 Python 3.9 或更高版本,而 ** 版本也适用于旧版本。两者都创建了一个新字典。相比之下,defaults.update(saved)和defaults |= saved改变了defaults。
理解和排序
字典推导式在单个可读行中构建新的字典,就像 列表推导式 对列表所做的那样:
prices = {"pen": 10, "book": 250, "bag": 900}
{k: v for k, v in prices.items() if v > 100}
# {'book': 250, 'bag': 900}
要按值排序,请将 key 函数传递给 sorted()。要查找具有最大值的键,请使用max():
sorted(prices.items(), key=lambda item: item[1], reverse=True)
# [('bag', 900), ('book', 250), ('pen', 10)]
max(prices, key=prices.get)
# 'bag'
字典没有 sort() 方法,sorted() 返回一个对的列表。如果您想要按该顺序的字典,请将结果包含在 dict() 中。
计数和分组模式
有两个任务不断出现。第一个是计数,您可以使用 get() 来执行此操作,默认值为零:
words = "to be or not to be".split()
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
print(counts)
# {'to': 2, 'be': 2, 'or': 1, 'not': 1}
标准库Counter使这个过程变得更短:
from collections import Counter
Counter(words).most_common(2)
# [('to', 2), ('be', 2)]
第二个是分组,defaultdict 在这里是理想的选择,因为它为您创建了缺失值:
from collections import defaultdict
orders = [("Asha", 1200), ("Ben", 300), ("Asha", 800)]
by_customer = defaultdict(list)
for name, total in orders:
by_customer[name].append(total)
print(dict(by_customer))
# {'Asha': [1200, 800], 'Ben': [300]}
如果没有它,您需要在附加之前检查每个键是否存在。这些相同的模式非常适合聚合 API 数据或日志行。当字典为空或键丢失时,我们的 Python 异常处理指南 展示了如何处理结果 KeyError。
嵌套数据和复制陷阱
JSON 直接映射到嵌套字典和列表,因此您经常会链接键。当关卡可能丢失时,链接 get() 可以保证其安全:
response = {"user": {"profile": {"city": "Pune"}}}
response["user"]["profile"]["city"] # 'Pune'
response.get("user", {}).get("settings", {}).get("theme") # None
复制嵌套数据时要小心。 copy() 仅复制顶层,因此内部字典与原始字典保持共享:
settings = {"db": {"host": "localhost"}}
shallow = settings.copy()
shallow["db"]["host"] = "prod"
print(settings["db"]["host"])
# prod
更改副本会更改原始版本,这可能是一个令人讨厌的错误。使用 copy.deepcopy(settings) 获得完全独立的副本。
什么可以作为字典键?
键必须是可哈希,这通常意味着不可变。字符串、数字和不可变值的元组都可以。列表和字典不会:
{["a"]: 1}
# TypeError: unhashable type: 'list'
原因是密钥的哈希决定了其值的存储位置。如果某个键可能发生变化,Python 将无法再找到它。如果需要复合键,请使用元组,例如 {("Pune", 2026): 120}。
常见错误
- 在可选键上使用方括号。 当某个键可能不存在时,请使用
get()。 - 假设
get()表示密钥存在。None可能表示丢失,或已存储None。当差异很重要时使用in。 - 使用可变的默认值。
dict.fromkeys(names, [])为每个键提供完全相同的列表。请改用理解式。 - 在迭代期间更改大小。 循环键的副本。
- 对固定的已知字段使用字典。 A
dataclass可以更清晰,并且它可以捕获字段名称中的拼写错误。
最后的话
字典奖励一点练习。请记住 get() 表示可选键,items() 表示循环,Counter 和 defaultdict 表示两个最常见的作业。为了进行练习,请使用一个小的 JSON 文件并编写代码来对其记录进行计数和分组。如果您是该语言的新手,请从我们的 Python 初学者教程 开始。
常见问题
Python 中的字典是什么?
字典是存储键和值对的内置集合。您可以通过键查找值,即使数据量很大,查找速度也很快。
Python 字典是有序的吗?
是的。从 Python 3.7 开始,字典保证保持键插入的顺序。更新现有密钥不会更改其位置。
get() 和方括号有什么区别?
当密钥丢失时,方括号会引发 KeyError。 get() 返回 None 或您提供的默认值,因此它适合可选的键。
字典可以有重复的键吗?
不,每个键都是唯一的。分配给现有键会替换其值,如果文本重复键,则最后一个值获胜。
如何在 Python 中合并两个字典?
使用 | b(Python 3.9 或更高版本),或 {**a, **b}(旧版本)。两者都构建一个新字典,当键冲突时,b 中的值获胜。
继续学习
需要测试、WordPress 或 SEO 方面的帮助?
我们帮助团队交付更好的软件并发展他们的网站。告诉我们您正在做什么,我们将建议明确的下一步。
更多指南 测试、人工智能和现代开发
喜欢这篇文章吗?选择一个主题并直接跳至我们最新的教程。
人工智能幻觉解释:语言模型为何会产生幻觉以及如何减少它
人工智能幻觉解释:它们是什么,为什么语言模型产生它们,常见类型,如何通过基础和提示来减少它们,以及我们进行的简单检查。
阅读文章 →DevOps环境变量解释:.env 文件、秘密和配置正确完成
使用我们运行的 Python 示例解释环境变量:读取和设置它们、为什么每个值都是字符串、.env 文件、进程继承、秘密和验证。
阅读文章 →软件开发API 速率限制解释:算法、标头和处理 429 错误
API 速率限制通过我们运行的模拟进行了解释:令牌桶、固定窗口、滑动窗口、429 响应、速率限制标头、带回退的重试和测试限制。
阅读文章 →测试自动化Python 中的模拟:unittest.mock、补丁以及导致测试谎言的错误
使用unittest.mock 在Python 中进行模拟,经过测试:模拟和return_value、side_effect、修补使用名称的位置、spec 和autospec、模拟日期以及常见错误。
阅读文章 →软件测试代码覆盖率解释:行覆盖率与分支覆盖率以及 100% 的真正含义
用真实的coverage.py运行来解释代码覆盖率:行、分支和条件覆盖率,阅读报告,为什么100%覆盖率仍然会错过错误,以及合理的目标。
阅读文章 →数据库与 SQLSQL 中的 DELETE、TRUNCATE 和 DROP:差异、回滚以及何时使用它们
DELETE、TRUNCATE 和 DROP 通过经过测试的 SQL 进行了解释:各自删除什么、回滚、触发器、身份重置、速度,以及 PostgreSQL、MySQL、SQL Server 和 SQLite 有何不同。
阅读文章 →数据库与 SQLSQL 视图解释:创建、使用和避免陷阱(附示例)
SQL 视图通过我们运行的查询进行解释:创建视图、实时结果、隐藏列、性能、可更新和物化视图、破坏的依赖关系和最佳实践。
阅读文章 →软件开发TypeScript 接口与类型:真正的差异,使用编译器进行测试
TypeScript 接口与类型,使用真实编译器进行检查:两者都可以做什么,只有一个可以做什么,声明合并,扩展与交集以及要遵循的简单规则。
阅读文章 →软件开发Python *args 和 **kwargs 解释:灵活的函数和清晰的示例
Python *args 和 **kwargs 用我们运行的代码进行了解释:打包和解包、参数顺序、仅关键字和仅位置参数、装饰器和常见错误。
阅读文章 →软件开发Python Lambda 函数:语法、实际用途以及何时不使用它们
Python lambda 函数用我们运行的代码进行了解释:语法、使用键排序、映射和过滤器、闭包、后期绑定陷阱,以及何时普通 def 是更好的选择。
阅读文章 →人工智能什么是人工智能代理?它们是如何工作的,只需运行一个简单的代理循环
什么是人工智能代理?关于代理循环、工具、内存和护栏的简单指南,以及我们运行的一个小型 Python 循环、真正的风险以及何时简单的聊天机器人是更好的选择。
阅读文章 →DevOps监控与可观察性:真正的区别,包括日志、指标和跟踪
监控与可观察性解释:已知和未知的故障、日志、指标和跟踪、检查事件演练、黄金信号、OpenTelemetry 和有用的警报。
阅读文章 →DevOpsDocker Volumes 与 Bind Mounts:以正确的方式保留容器数据
Docker 卷与绑定挂载解释:为什么容器数据消失、命名卷、绑定挂载、tmpfs、Compose 示例、备份、权限以及何时使用它们。
阅读文章 →测试自动化TDD 与 BDD:主要区别、以两种方式构建的一个功能以及何时使用每种方式
TDD 与 BDD 的解释是通过一种双向构建的折扣功能:使用我们运行的代码进行红绿重构、Given-When-Then 场景、工具、权衡以及何时使用每种方案。
阅读文章 →软件测试用户验收测试 (UAT):流程、清单和真实示例
用户验收测试解释:谁运行它、它与 QA 有何不同、七步流程、UAT 测试用例模板、清单、签核标准和常见错误。
阅读文章 →数据库与 SQLSQL NULL 值解释:IS NULL、COALESCE、NULLIF 和要避免的陷阱
通过我们运行的查询解释了 SQL NULL 值:三值逻辑、IS NULL、COALESCE、NULLIF,聚合、连接和排序如何处理 NULL,以及它悄悄引起的错误。
阅读文章 →数据库与 SQLSQL CASE WHEN 语句:语法、实例和常见错误
SQL CASE WHEN 解释了我们运行的查询:简单和搜索表单、条件顺序、SUM 透视、COUNT 技巧、自定义排序、更新和要避免的 NULL 陷阱。
阅读文章 →软件开发什么是智威汤逊?通过工作示例解释 JSON Web 令牌
什么是智威汤逊? JSON Web Tokens 解释:这三个部分,在我们运行的代码中构建和篡改的令牌,JWT 与会话,存储,刷新令牌和安全错误。
阅读文章 →软件开发JavaScript 事件循环解释:调用堆栈、微任务和计时器以及示例
JavaScript 事件循环用我们运行的代码进行了解释:调用堆栈、任务和微任务队列、为什么 setTimeout 0 不是立即执行、阻塞、饥饿和面试测验。
阅读文章 →软件开发Python 生成器和 Yield 解释:通过真实示例节省内存
Python 生成器和yield 用我们运行的代码进行了解释:它们如何暂停和恢复、测量内存节省、管道、无限序列、yield from、发送和常见陷阱。
阅读文章 →人工智能什么是嵌入?向量和余弦相似度简单解释
什么是嵌入?关于向量、余弦相似度和语义搜索的简单语言指南,其中包含我们运行的一个小示例、常见用途、选择模型和已知限制。
阅读文章 →DevOps蓝绿部署与金丝雀部署:差异、权衡以及如何选择
蓝绿部署与金丝雀部署解释:每种部署的工作原理、成本、风险和回滚、我们测试的稳定用户分桶、数据库迁移、滚动更新以及如何选择。
阅读文章 →测试自动化不稳定的测试:造成这些问题的原因以及如何彻底解决它们
我们运行的演示解释了不稳定的测试:主要原因、如何确认和诊断、正确的时间修复、共享状态和日期以及隔离过程。
阅读文章 →软件测试负载测试与压力测试:差异、指标和 k6 示例
负载测试与压力测试的解释:各自证明什么、峰值和浸泡测试、重要的指标、为什么平均值会误导、k6 个示例以及如何计划测试。
阅读文章 →软件测试测试用例与测试场景:主要区别、示例以及何时使用它们
测试用例与测试场景的解释:清晰的定义、并排的表格、从场景到案例的密码重置功能、模板以及何时使用每个功能。
阅读文章 →数据库与 SQLSQL 查询优化:读取执行计划并修复慢速查询(带计时)
对一百万行进行 SQL 查询优化测试:读取执行计划、添加正确的索引、修复不可控制的过滤器、使用复合索引和键集分页。
阅读文章 →数据库与 SQLSQL UNION 与 UNION ALL:差异、示例和性能测试
SQL UNION 与 UNION ALL 通过我们运行的查询进行了解释:重复、都遵循的规则、真实的数据错误、测量的性能、INTERSECT 和 EXCEPT 以及何时使用它们。
阅读文章 →软件开发JavaScript Fetch API 教程:GET、POST、错误处理和超时
针对本地服务器测试的 JavaScript Fetch API 教程:GET 和 POST、为什么不抛出 404、可重用的帮助程序、查询字符串、超时、CORS 和常见错误。
阅读文章 →软件开发Python 文件处理:读取、写入、CSV、JSON 和 pathlib 以及示例
使用我们运行的代码解释了 Python 文件处理:打开模式、使用、读取大文件、CSV、JSON、pathlib、二进制文件、安全写入、错误处理和常见错误。
阅读文章 →软件开发Python 类和对象:带有实际示例的 OOP 教程
用我们运行的代码解释 Python 类和对象:__init__、方法、类与实例属性、继承、属性、dunder 方法、数据类和常见错误。
阅读文章 →人工智能什么是大语言模型?法学硕士如何运作,在没有炒作的情况下进行解释
什么是大语言模型?法学硕士用简单的语言解释:标记、嵌入、注意力、训练、温度和上下文窗口、一个微小的下一个单词演示和真正的限制。
阅读文章 →DevOps适合初学者的 Linux 命令:带有示例的基本终端指南
适合初学者的 Linux 命令,按任务分组:导航、文件、查看日志、grep、管道、权限、进程和档案,并附有实用的日志分析示例。
阅读文章 →测试自动化Selenium 与 Playwright:主要区别、代码比较以及选择
Selenium 与 Playwright 比较:架构、等待、浏览器和语言支持、调试、两种工具中的相同测试、迁移建议以及如何选择。
阅读文章 →软件测试等价划分:通过实例解释测试设计技术
等效分区解释:如何找到有效和无效分区,年龄、密码和优惠券的工作示例,我们运行的测试,以及为什么将其与边界配对。
阅读文章 →软件测试软件测试中的严重性与优先级:差异、矩阵和实例
软件测试中的严重性与优先级解释:清晰的定义、带有示例的四向矩阵、级别尺度、谁设置每个级别以及如何运行错误分类。
阅读文章 →数据库与 SQLSQL 子查询教程:类型、相关子查询和 EXISTS 以及示例
SQL 子查询教程,其中包含我们运行的查询:标量、IN、FROM 和 SELECT 子查询、相关子查询、EXISTS、NOT IN NULL 陷阱以及子查询与 JOIN 与 CTE。
阅读文章 →数据库与 SQLSQL 事务和 ACID 解释:COMMIT、ROLLBACK 和隔离级别
SQL 事务和 ACID 通过我们运行的银行转账进行了解释:COMMIT、ROLLBACK、保存点、锁、隔离级别、脏读、死锁和最佳实践。
阅读文章 →软件开发Git 命令备忘单:您实际使用的命令,以及示例
Git 命令备忘单按任务分组:设置、暂存、分支、远程、存储、历史记录和撤消错误,以及来自真实演示存储库的输出。
阅读文章 →软件开发JavaScript Promise 解释:then、catch、Promise.all 和常见错误
JavaScript 承诺用我们运行的代码进行了解释:状态、then 和 catch 链、错误处理、Promise.all、allSettled、race 和 any、事件循环和常见错误。
阅读文章 →软件开发Python 字典教程:方法、示例和常见模式
Python 字典教程,包含我们运行的代码:创建、读取和更新字典、关键方法、合并、理解、计数和分组模式以及常见错误。
阅读文章 →人工智能什么是 RAG?通过工作示例解释检索增强生成
什么是RAG?检索增强生成逐步解释:索引、分块、嵌入、检索、一个小型的 Python 工作示例、评估和常见故障。
阅读文章 →DevOpsTerraform 初学者教程:从第一个文件到模块的基础设施即代码
适合初学者的 Terraform 教程:从没有云帐户开始,学习初始化、计划和应用,然后是变量、输出、状态、模块和安全的团队工作流程。
阅读文章 →DevOpsDocker 与 Kubernetes:主要区别、它们如何协同工作以及您需要哪些
Docker 与 Kubernetes 的解释:各自的作用、同一个应用程序同时运行、Docker Compose 和 Swarm 的比较、dockershim 的变化以及如何决定您需要什么。
阅读文章 →测试自动化Pytest 初学者教程:夹具、参数化和真实示例
面向初学者的 pytest 教程,其中包含我们在 pytest 9.2 上运行的测试:断言、固定装置、参数化、conftest、标记、tmp_path、monkeypatch、有用的标志和 CI。
阅读文章 →软件测试软件测试生命周期 (STLC):6 个阶段、进入和退出标准、示例
软件测试生命周期解释:六个 STLC 阶段,包括进入和退出标准、可交付成果、有效的登录功能示例、STLC 与 SDLC 以及敏捷中的 STLC。
阅读文章 →软件开发Git merge 与 rebase 的区别:示例及如何选择
用真实的 log 输出、对比表、rebase 黄金法则和安全的团队工作流,讲清 Git merge 与 rebase 的区别。
阅读文章 →软件开发Python 列表推导式:语法、示例与何时避免使用
Python 列表推导式详解:语法、过滤、if-else、嵌套循环、实测耗时,以及何时普通 for 循环更合适。
阅读文章 →数据库与 SQLSQL JOIN 详解:附示例(INNER、LEFT、RIGHT、FULL)
通过示例表和查询,一步步讲解 SQL JOIN:INNER、LEFT、RIGHT、FULL、CROSS 和 SELF,并介绍常见错误与性能技巧。
阅读文章 →