导读:本期聚焦于阿狸创作的《Python字典是如何实现键值对存储的?常用方法有哪些?》,敬请观看详情。为什么Python字典的查找速度这么快?为什么字典的键必须是不可变类型?这背后其实是哈希表在发挥作用。本文将从字典的底层实现讲起,带你了解键值对的存储原理、哈希冲突的处理方式以及键的可哈希性要求,同时系统整理get、setdefault、update、pop、items、keys、values等常用方法的用法和适用场景,并结合代码示例说明遍历字典、合并字典、嵌套字典处理的实用技巧,帮助你真正掌握Python字典这个高频数据结构。

字典(dict)是Python中使用频率最高的数据结构之一,它以键值对的形式组织数据,查找效率极高。很多初学者会用字典,却不太清楚它背后的存储机制,比如为什么字典的键不能是列表、为什么遍历字典的顺序和插入顺序一致。理解字典的底层实现,能帮助你在写代码时做出更合理的选择,也能在遇到性能问题时快速定位原因。

Python字典是如何实现键值对存储的?常用方法有哪些?

字典的底层实现:哈希表是如何工作的

Python字典的核心是一张哈希表。当你执行d[key] = value时,Python会先对key调用hash()函数,得到一个哈希值,再根据这个哈希值计算出该键值对在内部数组中的存储位置。查找时同样走这条路径:先算哈希值,再定位索引,最后比较键是否相等。整个过程不需要遍历整个字典,时间复杂度接近O(1),这就是字典查找快的原因。

既然不同对象的哈希值可能相同,也就是出现哈希冲突,Python是怎么处理的呢?早期版本的CPython使用开放定址法,冲突时按探测序列寻找下一个空位。Python 3.6之后,字典的实现做了重大改进,引入了紧凑字典(compact dict)的结构:一张稀疏的索引表加一张密集的键值对数组。索引表只存整数下标,键值对按插入顺序紧凑排列。这种设计既节省了内存,又让字典天然保持插入顺序,这也是从Python 3.7开始官方保证字典有序的原因。

理解了哈希机制,也就明白了为什么键必须是不可变类型。列表是可变的,如果允许它做键,修改列表内容后其哈希值会与存储时不一致,就再也找不到原来的键值对了。所以字符串、数字、元组(元组内也不能含可变元素)都可以做键,而列表和字典不行。可以动手验证一下:

d = {}
d[([1, 2])] = "test"  # 会抛出 TypeError: unhashable type: 'list'

# 元组是不可变的,可以作为键
point = {}
point[(3, 5)] = "坐标A"
print(point[(3, 5)])  # 输出:坐标A

字典的创建与常用读写方法

创建字典有多种方式,最常见的是花括号语法和dict()构造函数。如果要根据两个序列快速组装字典,zip()配合dict()非常方便。还有一种字典推导式,适合从已有数据中筛选生成新字典。

# 三种常见创建方式
d1 = {"name": "张三", "age": 25}
d2 = dict(name="李四", age=30)
d3 = dict(zip(["a", "b", "c"], [1, 2, 3]))

# 字典推导式:筛选出成绩及格的学生
scores = {"小明": 88, "小红": 45, "小刚": 92}
passed = {name: score for name, score in scores.items() if score >= 60}
print(passed)  # 输出:{'小明': 88, '小刚': 92}

读取字典时,直接用中括号d[key]是最快的,但键不存在时会抛出KeyErrorget()方法则更安全,可以在键缺失时返回默认值而不报错,这在处理配置项、统计词频等场景特别实用。

config = {"host": "127.0.0.1", "port": 8080}

# 中括号访问,键不存在会报错
print(config["host"])

# get方法访问,键不存在返回默认值
print(config.get("timeout", 30))  # 输出:30

# 统计词频的经典写法
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
counter = {}
for w in words:
    counter[w] = counter.get(w, 0) + 1
print(counter)  # 输出:{'apple': 3, 'banana': 2, 'cherry': 1}

新增和修改比较简单,直接赋值即可,键存在就是修改,不存在就是新增。setdefault()方法适合处理嵌套结构:如果键不存在就先设置默认值再返回,存在则直接返回已有值,常用于构建多级字典。

data = {}
data.setdefault("users", []).append("张三")
data.setdefault("users", []).append("李四")
print(data)  # 输出:{'users': ['张三', '李四']}

# 对比直接赋值的繁琐写法
if "logs" not in data:
    data["logs"] = []
data["logs"].append("系统启动")

删除、合并与遍历技巧

删除元素有几种方式。pop()删除指定键并返回对应的值,键不存在时可给默认值避免报错;popitem()删除并返回最后插入的键值对,配合循环可以清空字典;del语句适合直接删除确定存在的键;clear()则一次性清空整个字典。

user = {"name": "王五", "age": 28, "city": "北京"}

name = user.pop("name")          # 删除并返回值
age = user.pop("age")            
last = user.popitem()            # 删除并返回最后一个键值对
del user["city"]                 # 直接删除
user.clear()                     # 清空字典

合并字典时,update()方法会用另一个字典的内容覆盖当前字典的同名键,常用于配置合并。从Python 3.5起还可以用{**d1, **d2}解包语法,Python 3.9之后更是支持||=运算符,写法越来越简洁。

default_cfg = {"host": "127.0.0.1", "port": 8080, "debug": False}
custom_cfg = {"port": 9090, "debug": True}

# 方式一:update,会修改原字典
merged = default_cfg.copy()
merged.update(custom_cfg)

# 方式二:解包语法,生成新字典
merged = {**default_cfg, **custom_cfg}

# 方式三:Python 3.9+ 合并运算符
merged = default_cfg | custom_cfg
print(merged)  # 输出:{'host': '127.0.0.1', 'port': 9090, 'debug': True}

遍历字典时,keys()values()items()三个方法分别返回键、值和键值对视图。视图对象是动态的,遍历过程中修改字典会导致RuntimeError,这一点要特别注意。如果确实需要在遍历时删除元素,可以先用list()把键固定下来。

scores = {"小明": 88, "小红": 45, "小刚": 92}

# 遍历键值对
for name, score in scores.items():
    print(f"{name}的分数是{score}")

# 遍历时删除不及格的学生,需要先转成列表
for name in list(scores.keys()):
    if scores[name] < 60:
        del scores[name]
print(scores)  # 输出:{'小明': 88, '小刚': 92}

此外还有一些细节值得留意:判断键是否存在用in运算符而不是get(),语义更清晰;fromkeys()可以快速生成所有值相同的字典;处理深层嵌套字典时,标准库的collections.defaultdictsetdefault()更灵活,ChainMap则适合多个字典串联查询的场景。掌握这些方法后,字典基本可以应对日常开发中绝大多数的数据组织需求。

Python字典哈希表字典常用方法修改时间:2026-09-06 10:50:34

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260906/51498.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。