1_7_字典和字典操作#
作者: ZhouLong
创建日期: 2026 年 01 月 14 日
版本: 1.0
浏览量:
1. 字典的基本概念#
字典(Dictionary)是Python中由键值对元素构成的。其特征是每个元素都是一个键值对(key-value pair),键和值之间用冒号分隔,元素之间用逗号分隔,整个字典包括在花括号{}中。
1.1 字典的特点#
无序:元素存储顺序不固定(Python 3.7+开始保持插入顺序,但仍被视为无序数据结构)
key(键)必须唯一且不可变(字符串、数字、元组可作为键)
value(值)可以是任意数据类型,且可重复
通过键而不是索引访问元素
2. 字典的创建#
2.1 直接创建
#
创建字典(Dictionary)最基本的方法是使用花括号 {}。
空字典:直接用
{}创建,表示一个不含任何键值对的字典。包含元素的字典:在花括号内用逗号分隔键值对,每个键值对使用冒号
:连接键和值。字典可以嵌套复杂数据类型(如列表、其他字典)作为值。
下面的代码示例演示了如何直接创建一个空字典和一个包含学生信息的字典,其中学生信息包括姓名、年龄、专业和成绩列表。
# 创建空字典
empty_dict = {}
print(f"空字典: {empty_dict}")
# 创建包含元素的字典
student = {
"name": "张三",
"age": 20,
"major": "计算机科学",
"grades": [85, 90, 92]
}
print(student) # {'name': '张三', 'age': 20, 'major': '计算机科学', 'grades': [85, 90, 92]}
2.2 使用dict()构造函数
#
除了直接使用花括号创建字典,还可以使用内置的 dict() 构造函数。这种方法提供了更灵活的创建方式,适用于从不同数据结构或动态数据生成字典。
关键字参数创建:将键作为关键字参数传递给
dict(),例如dict(name="李四", age=25),键会自动转为字符串。可迭代对象创建:传递一个包含键值对元组的列表(如
[("x", 10), ("y", 20)]),dict()会将其转换为字典。使用
zip()函数:将两个列表(一个键列表、一个值列表)通过zip()组合成键值对序列,再转换为字典,适合批量创建。
下面的代码示例展示了使用 dict() 构造函数的三种常见方法:通过关键字参数、元组列表,以及结合 zip() 函数从两个列表合并创建字典。
# 使用键值对创建
person = dict(name="李四", age=25, city="北京")
print(f"人员信息: {person}") # 人员信息: {'name': '李四', 'age': 25, 'city': '北京'}
# 使用元组列表创建
coordinates = dict([("x", 10), ("y", 20), ("z", 30)])
print(f"坐标: {coordinates}") # 坐标: {'x': 10, 'y': 20, 'z': 30}
# 使用zip函数合并两个列表
keys = ["a", "b", "c"]
values = [1, 2, 3]
combined_dict = dict(zip(keys, values))
print(f"合并后的字典: {combined_dict}") # 合并后的字典: {'a': 1, 'b': 2, 'c': 3}
3. 字典的基本操作#
3.1 访问字典元素
#
访问字典元素主要通过键(key)来获取对应的值(value)。有两种常用方法:
直接使用键访问:通过方括号
[]和键名直接获取值,例如employee['name']。但如果键不存在,会引发KeyError错误。使用
get()方法:通过字典.get(键, 默认值)安全地访问值。如果键存在,返回对应值;如果键不存在,返回指定的默认值(默认为None),避免程序因键错误而中断。
下面的代码示例演示了如何从员工字典中访问姓名、部门等信息,并对比了直接访问和使用 get() 方法的区别,后者在处理可能缺失的键时更安全。
# 创建示例字典
employee = {
"id": 1001,
"name": "王五",
"department": "研发部",
"salary": 15000.0,
"skills": ["Python", "Java", "SQL"]
}
# 使用键访问值
print(f"员工姓名: {employee['name']}") # 员工姓名: 王五
print(f"员工部门: {employee['department']}") # 员工部门: 研发部
# 使用get()方法访问(更安全,避免KeyError)
print(f"员工薪资: {employee.get('salary')}") # 员工薪资: 15000.0
print(f"员工邮箱: {employee.get('email', '未设置')}") # 员工邮箱: 未设置
3.2 修改字典元素
#
修改字典元素主要包括更新现有键的值、添加新键值对以及批量更新操作。由于字典是可变的,这些操作都可以直接进行。
修改现有值:通过指定键并赋值,例如
employee["salary"] = 16000.0,如果键已存在,其对应值会被覆盖。添加新键值对:直接对新键赋值,例如
employee["email"] = "wangwu@company.com",如果键不存在,则会新增该键值对。批量更新
update():使用update()方法,传入一个字典或键值对可迭代对象,批量更新或添加多个键值对,例如employee.update({"level": "P7"})。
下面的代码示例展示了如何调高员工薪资、添加邮箱和入职日期,并通过 update() 批量更新职级和年假天数。
# 修改现有键的值
employee["salary"] = 16000.0
print(f"调薪后: {employee}")
# 添加新键值对
employee["email"] = "wangwu@company.com"
employee["hire_date"] = "2023-01-15"
print(f"添加信息后: {employee}")
# 批量更新update()
employee.update({
"level": "P7",
"annual_leave": 15
})
print(f"批量更新后: {employee}")
3.3 删除字典元素
#
删除字典元素有多种方法,可根据需要移除单个键值对或清空整个字典。操作时需注意避免引用不存在的键。
del语句:使用del 字典[键]删除指定键及其值,键不存在会引发KeyError。pop()方法:使用字典.pop(键, 默认值)删除指定键并返回其值。如果键不存在,可提供默认值避免错误。popitem()方法:移除并返回最后插入的键值对(Python 3.7+ 中字典有序)。字典为空时引发KeyError。clear()方法:清空字典所有键值对,使其变为空字典{}。
下面的代码示例在字典副本上演示了这些删除操作:用 del 删除入职日期,用 pop() 移除职级并获取值,用 popitem() 删除最后一项,最后用 clear() 清空字典。
# 创建副本进行操作
employee_copy = employee.copy()
# 使用del删除指定键
del employee_copy["hire_date"]
print(f"删除hire_date后: {employee_copy}")
# 使用pop()删除并返回值
removed_value = employee_copy.pop("level")
print(f"删除的level值: {removed_value}")
print(f"删除后: {employee_copy}")
# 使用popitem()删除最后一个元素(Python 3.7+)
last_item = employee_copy.popitem()
print(f"删除的最后一项: {last_item}")
print(f"删除后: {employee_copy}")
# 清空字典
employee_copy.clear()
print(f"清空后: {employee_copy}")
4. 字典的常用方法#
4.1 获取字典信息
#
字典提供了多种方法来获取其内部信息,包括键、值、键值对以及字典大小等。这些方法返回的是视图对象(view objects),可动态反映字典的变化。
keys():返回字典所有键的视图,常用于遍历或检查键的存在。values():返回字典所有值的视图,用于处理值的集合。items():返回字典所有键值对的视图,每个键值对以元组形式表示,便于同时访问键和值。len():返回字典中键值对的数量,即字典长度。in操作符:检查指定键是否存在于字典中,返回布尔值。
下面的代码示例从库存字典中获取所有水果名称(键)、库存数量(值)和完整条目(键值对),计算字典长度,并检查特定水果是否存在。
inventory = {
"apple": 50,
"banana": 30,
"orange": 40,
"grape": 25
}
# 获取所有键
keys = inventory.keys()
print(f"所有键: {list(keys)}")
# 获取所有值
values = inventory.values()
print(f"所有值: {list(values)}")
# 获取所有键值对
items = inventory.items()
print(f"所有键值对: {list(items)}")
# 获取字典长度
print(f"字典长度: {len(inventory)}")
# 检查键是否存在
print(f"是否存在apple: {'apple' in inventory}")
print(f"是否存在pear: {'pear' in inventory}")
4.2 字典遍历
#
遍历字典是指逐个访问其中的键值对,这是处理字典数据的基本操作。Python提供了简洁的方式来遍历键、值或两者同时遍历。
遍历键:使用
for key in 字典.keys():或直接for key in 字典:(默认遍历键),依次访问每个键。遍历值:使用
for value in 字典.values():,直接访问每个值。遍历键值对:使用
for key, value in 字典.items():,同时获取键和值,这是最常用的遍历方式。结合
enumerate():使用enumerate(字典.items(), start)在遍历时获取索引(从start开始),便于记录位置或序号。
下面的代码示例展示了如何遍历库存字典:分别遍历键、值和键值对,并演示了如何使用 enumerate() 为每个条目添加序号。
# 遍历所有键
print("遍历所有键:")
for key in inventory.keys():
print(f"键: {key}")
# 遍历所有值
print("\n遍历所有值:")
for value in inventory.values():
print(f"值: {value}")
# 遍历所有键值对
print("\n遍历所有键值对:")
for key, value in inventory.items():
print(f"{key}: {value}")
# 使用enumerate获取索引
print("\n带索引的遍历:")
for i, (key, value) in enumerate(inventory.items(), 1):
print(f"{i}. {key}: {value}")
5. 字典推导式
#
字典推导式(Dictionary Comprehension)是Python中一种简洁、高效地创建字典的方法,其语法类似于列表推导式,但生成的是键值对。它可以使代码更简洁、可读性更强。
基本语法:
{键表达式: 值表达式 for 变量 in 可迭代对象},通过循环从可迭代对象生成键值对。添加条件过滤:可以在推导式末尾添加
if条件,例如{x: x**2 for x in numbers if x % 2 == 0},仅对满足条件的元素生成键值对。转换现有字典:通过遍历现有字典的
items(),对键或值进行变换,生成新字典。合并两个序列:结合
zip()函数,将两个列表(或可迭代对象)配对为键值对。
下面的代码示例演示了如何使用字典推导式:从数字列表创建平方字典、过滤偶数平方、对库存字典中的值打九折,以及从水果和价格列表创建价格字典。
# 基本字典推导式
numbers = [1, 2, 3, 4, 5]
squared_dict = {x: x**2 for x in numbers}
print(f"平方字典: {squared_dict}")
# 带条件的字典推导式
even_squares = {x: x**2 for x in numbers if x % 2 == 0}
print(f"偶数的平方: {even_squares}")
# 转换现有字典
inventory_discount = {item: count * 0.9 for item, count in inventory.items()}
print(f"打九折后的库存: {inventory_discount}")
# 使用两个列表创建字典
fruits = ["apple", "banana", "orange", "grape"]
prices = [5.0, 3.0, 4.0, 8.0]
fruit_prices = {fruit: price for fruit, price in zip(fruits, prices)}
print(f"水果价格: {fruit_prices}")
6. 嵌套字典
#
嵌套字典是指字典的值本身也是字典(或其它容器),形成多层结构。这种结构适合表示复杂、分层次的数据,例如组织机构、配置信息等。
创建嵌套字典:直接在字典的值位置放置另一个字典,形成多层嵌套,如示例中的部门信息和公司信息。
访问嵌套元素:使用连续方括号逐层访问,例如
company['departments']['研发部']['manager'],从外到内依次指定每一层的键。修改嵌套值:与访问类似,通过多层键定位到具体位置后直接赋值,例如修改研发部人数或公司地点。
添加新嵌套结构:可以直接为外层字典的键赋值一个新的字典,从而添加一个完整的嵌套层级,如新增财务部信息。
下面的代码示例展示了一个包含部门和公司信息的嵌套字典,演示了如何访问、修改和添加嵌套内容。这种结构在实际应用中广泛用于管理复杂数据关系。
# 创建嵌套字典
company = {
"departments": {
"研发部": {
"manager": "张三",
"employee_count": 15,
"budget": 500000
},
"市场部": {
"manager": "李四",
"employee_count": 8,
"budget": 300000
},
"人事部": {
"manager": "王五",
"employee_count": 5,
"budget": 200000
}
},
"company_info": {
"name": "ABC科技有限公司",
"location": "北京市",
"established": 2010
}
}
# 访问嵌套字典
print(f"研发部经理: {company['departments']['研发部']['manager']}")
print(f"公司名称: {company['company_info']['name']}")
# 修改嵌套字典
company['departments']['研发部']['employee_count'] = 18
company['company_info']['location'] = "北京市海淀区"
# 添加新的嵌套结构
company['departments']['财务部'] = {
"manager": "赵六",
"employee_count": 6,
"budget": 250000
}
print(f"更新后的公司结构: {company}")
7. 字典的高级操作#
7.1 字典合并
#
字典合并是将多个字典的内容整合到一个字典中,Python 3.9+ 提供了多种方法。
**解包操作符:使用{**dict1, **dict2, **dict3}语法,将多个字典解包合并。如果存在重复键,后面的字典会覆盖前面的值(如示例中dict3的"a": 10覆盖了dict1的"a": 1)。|合并操作符(Python 3.9+):使用dict1 | dict2 | dict3,效果与**解包相同,语法更直观,但需注意Python版本兼容性。
下面的代码示例展示了如何使用 ** 操作符合并三个字典(其中包含重复键 "a"),并注释了 | 操作符的用法。合并后的字典包含所有键值对,重复键的值以最后一个字典为准。
# 使用**操作符合并字典
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
dict3 = {"e": 5, "a": 10} # 注意:a重复
# 合并字典(后面的字典覆盖前面的)
merged_dict = {**dict1, **dict2, **dict3}
print(f"合并后的字典: {merged_dict}")
# 使用|操作符合并(Python 3.9+)
# merged_dict = dict1 | dict2 | dict3
7.2 字典排序
#
字典本身是无序的(Python 3.6及之前)或保持插入顺序(Python 3.7+),但可通过排序生成一个新的有序字典。排序通常基于键或值。
按键排序:使用
sorted(字典.items()),默认按键排序(升序),返回键值对元组的列表,再通过dict()转为字典。按值排序:使用
sorted(字典.items(), key=lambda item: item[1]),其中key=lambda item: item[1]指定按值(元组第二个元素)排序。降序排序:添加参数
reverse=True,可实现降序排列。
下面的代码示例展示了如何对未排序字典进行按键排序、按值升序排序和按值降序排序,并将排序结果转换为新字典。排序操作不会改变原字典,而是生成新字典。
# 按键排序
unsorted_dict = {"z": 3, "a": 1, "m": 2, "c": 4}
# 返回排序后的新字典(Python 3.7+)
sorted_by_key = dict(sorted(unsorted_dict.items()))
print(f"按键排序: {sorted_by_key}")
# 按值排序
sorted_by_value = dict(sorted(unsorted_dict.items(), key=lambda item: item[1]))
print(f"按值排序: {sorted_by_value}")
# 按值降序排序
sorted_desc = dict(sorted(unsorted_dict.items(), key=lambda item: item[1], reverse=True))
print(f"按值降序排序: {sorted_desc}")
8. 字典与JSON转换
#
字典与JSON(JavaScript Object Notation)可以方便地相互转换,因为它们的结构非常相似。Python通过内置的 json 模块实现这一功能,常用于数据存储、传输和配置文件处理。
字典转JSON:
json.dumps(字典):将字典转换为JSON格式字符串。参数ensure_ascii=False确保中文字符正常显示,indent=2添加缩进美化输出。json.dump(字典, 文件对象):将字典直接写入JSON文件。
JSON转字典:
json.loads(JSON字符串):将JSON字符串解析为字典。json.load(文件对象):从JSON文件读取并转换为字典。
下面的代码示例展示了如何将包含嵌套结构和多种数据类型的字典转换为格式化的JSON字符串并保存到文件,然后再从文件读取JSON并转换回字典。这种转换在Web API、配置管理等场景中非常常见。
import json
# 字典转JSON
data_dict = {
"name": "张三",
"age": 30,
"married": True,
"children": None,
"hobbies": ["阅读", "游泳", "编程"],
"address": {
"city": "北京",
"street": "中关村大街"
}
}
# 转换为JSON字符串
json_str = json.dumps(data_dict, ensure_ascii=False, indent=2)
print("字典转JSON字符串:")
print(json_str)
# 保存到文件
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data_dict, f, ensure_ascii=False, indent=2)
# JSON转字典
with open("data.json", "r", encoding="utf-8") as f:
loaded_dict = json.load(f)
print("\nJSON转回字典:")
print(f"类型: {type(loaded_dict)}")
print(f"内容: {loaded_dict}")
9. 字典性能
#
字典在Python中是一种高效的数据结构,其核心优势在于基于哈希表的实现,使得大多数操作具有平均 O(1) 的时间复杂度,即操作时间基本不随数据量增加而显著增长。
查找操作:通过键查找值(如
large_dict[999999])的速度极快,因为哈希表直接定位键的位置,无需遍历。成员检查:使用
in检查键是否存在(如999999 in large_dict)同样高效,也是基于哈希查找。时间复杂度:在理想情况下,插入、删除、查找等操作的平均时间复杂度为 O(1),但在哈希冲突较多时可能退化为 O(n)。不过Python的字典实现已优化,日常使用中性能很高。
下面的代码示例通过一个包含100万个元素的字典,测试了键查找和成员检查的执行时间(毫秒级),展示了字典在处理大规模数据时仍能保持高效。因此,字典适合需要快速查找、去重或映射关系的场景。
import time
# 字典查找性能测试
large_dict = {i: f"value_{i}" for i in range(10000000)}
# 测试键查找速度
start_time = time.time()
_ = large_dict[999999] # O(1)时间复杂度
end_time = time.time()
print(f"字典查找时间: {(end_time - start_time)*10000:.9f}毫秒")
# 测试成员检查
start_time = time.time()
_ = 999999 in large_dict # O(1)时间复杂度
end_time = time.time()
print(f"成员检查时间: {(end_time - start_time)*10000:.9f}毫秒")
掌握字典操作对于编写高效、可读的Python代码至关重要。