1. 字典的初识
1.1 字典核心定义
字典(Dictionary)是 Python 中以「键值对(key-value)」 存储数据的映射型数据结构,通过键(key) 快速定位值(value),是 Python 最常用的数据结构之一。
- 语法:用大括号 {} 包裹,键值对用 : 分隔,多个键值对用 , 分隔
- 规则:键必须唯一且不可变(字符串 / 数字 / 元组),值可任意类型(字符串、列表、字典等)
1.2 字典与列表对比
列表靠索引定位数据,含义模糊;字典靠键定位数据,语义清晰。
# 列表:按索引存储,无法直观知道每个数据的含义
info_list = ["yuan", 18, 185, 70]
# 字典:按键值对存储,name/age/height明确表示数据含义
info_dict = {"name": "yuan", "age": 18, "height": 185, "weight": 70}
# 查看数据类型,输出<class 'dict'>
print(type(info_dict))1.3 通俗类比:新华字典
字典就像我们用的新华字典:
- 音节表(查字索引)= 字典的键(key)
- 对应的汉字 = 字典的值(value)
- 查字靠音节,查字典靠键,查询效率极高
2. 字典的存储原理(哈希 / 散列表)
2.1 哈希(Hash)基础
哈希是将任意长度输入,通过算法转为固定长度散列值的函数,是字典实现高效查询的核心。
2.2 字典的存储结构
字典本质是散列表(稀疏数组),每个存储单元叫bucket,包含两部分:
- 键对象的引用
- 值对象的引用
- 通过偏移量直接定位 bucket
2.3 键值对存储过程
# 1. 创建空字典
d = {}
# 2. 向字典添加键值对:key="name",value="yuan"
d["name"] = "yuan"
# 3. 计算key的哈希值,并转为二进制形式
print(bin(hash("name")))
0b100000010000100110101111111010000110111010101111110001000101111
-0b11110101000101000110100000000001000100111100110000010110100010存储步骤:
- 计算 key 的哈希值 → 取二进制最后 3 位作为偏移量
- 检查对应偏移量的 bucket 是否为空
- 为空则存入;不为空则顺延下一个偏移量,直到找到空 bucket
2.4 字典查询过程
# 方式1:直接通过键查询(键不存在会直接报错)
d["name"]
print(d["name"])
KeyError: 'name'
# 方式2:get()安全查询(键不存在返回None,不报错)
d.get("name")
print(d.get("name"))
None查询步骤:
- 计算目标 key 的哈希值 → 取偏移量定位 bucket
- 对比 bucket 中 key 的哈希值与目标 key
- 一致则返回值;不一致则顺延,无结果返回 None
2.5 哈希值每次不同的原因
Python 每次启动会随机生成哈希种子,防止哈希碰撞攻击,提升数据安全性。
d = {}
d["name"] = "yuan"
计算key的哈希值,并转为二进制形式
print(bin(hash("name")))
0b1101100101011000100110001100011100110110101001101101101010 #第一次
-0b11110101000101000110100000000001000100111100110000010110100010 #第二次3. 字典的核心特点
- 无序性:无索引,靠键访问(Python3.7 + 默认保留插入顺序)
- 键的特性:唯一、不可变,不可重复
- 可变性:支持增 / 删 / 改键值对,动态调整数据
4. 字典的基本操作
4.1 创建字典
# 直接用{}创建字典
gf = {"name":"高圆圆","age":32}
# 查看字典中键值对的总数量
print(len(gf)) # 输出:24.2 查询键值
gf = {"name":"张三","age":33}
# 通过键直接取值(键不存在会报错)
print(gf["name"]) # 输出:张三
print(gf["age"]) # 输出:334.3 添加 / 修改键值对
- 键已存在 → 修改对应值
- 键不存在 → 添加新键值对
gf = {"name":"张三","age":33}
# 键age已存在,执行修改操作
gf["age"] = 29
print(gf)
# 输出结果
{'name': '张三', 'age': 29}
# 键gender不存在,执行添加操作
gf["gender"] = "female"
print(gf)
# 输出结果
{'name': '张三', 'age': 29, 'gender': 'female'}4.4 删除键值对
gf = {"name":"张三","age":32,"gender":"female"}
# 删除指定键值对:删除age键
del gf["age"]
print(gf)
# 输出结果
{'name': '张三', 'gender': 'female'}
# 删除整个字典变量(删除后无法访问)
del gf
print(gf)
# 输出结果
报错:name 'gf' is not defined4.5 删除键值对
gf = {"name":"张三","age":32}
# 判断"weight"是否为字典的键
print("weight" in gf) # 输出:False4.6 循环遍历字典
gf = {"name":"张三","age":32}
# 遍历字典所有键,通过键获取对应值
for key in gf:
print(key, gf[key])
# 输出结果:
# name 张三
# age 325. 字典常用内置方法
| 方法名 | 作用 |
| update() | 批量添加 / 修改键值对 |
| pop() | 删除指定键,返回对应值 |
| popitem() | 删除最后一个键值对 |
| clear() | 清空字典所有数据 |
| get() | 安全取值,不存在返回 None |
| keys() | 获取所有键 |
| values() | 获取所有值 |
| items() | 获取所有键值对(元组) |
| dict.fromkeys() | 批量创建键,统一赋值 |
5.1 方法案例
# 初始化基础字典
d = {"name":"yuan","age":18}
# 1. update():批量修改+添加键值对
d.update({"age": 19,"height":"190cm"})
print(d) # {'name': 'yuan', 'age': 19, 'height': '190cm'}
# 2. pop():删除指定键"age",返回被删除的值19
d.pop("age")
print(d) # {'name': 'yuan', 'height': '190cm'}
# 3. popitem():删除最后一个键值对
d.popitem()
print(d) # {'name': 'yuan'}
# 4. clear():清空字典,变为空字典
d.clear()
print(d) # {}
# 重新初始化字典
d = {"name":"yuan","age":18}
# 5. get():安全查询,键不存在返回None
print(d.get("name")) # yuan
# 6. keys():获取字典所有键
print(d.keys()) # dict_keys(['name', 'age'])
# 7. values():获取字典所有值
print(d.values()) # dict_values(['yuan', 18])
# 8. items():获取所有键值对(元组形式)
print(d.items()) # dict_items([('name', 'yuan'), ('age', 18)])
# 9. dict.fromkeys():批量创建键,统一赋值60
knowledge = ['语文', '数学', '英语']
scores = dict.fromkeys(knowledge, 60)
print(scores) # {'语文': 60, '数学': 60, '英语': 60}
# 综合演示
gf = {"name": "张三", "age": 32}
# get()安全取值
print(gf.get("name")) # 张三
# update()修改年龄+添加体重
gf.update({"age": 18, "weight": "50kg"})
print(gf) # {'name': '张三', 'age': 18, 'weight': '50kg'}
# pop()删除weight键,接收被删除的值
ret = gf.pop("weight")
print(gf) # {'name': '张三', 'age': 18}
# items()遍历键值对
for k, v in gf.items():
print(k, v)6. 列表与字典嵌套
6.1 案例 1:字典值为列表(引用传递)
# 定义普通列表
l1 = [3, 4, 5]
# 定义字典,c键指向列表l1(引用传递,共享同一份数据)
d1 = {"a": 1, "b": 2, "c": l1}
# 向原列表添加元素,字典中的c值同步变化
l1.append(6)
print(d1) # {'a': 1, 'b': 2, 'c': [3, 4, 5, 6]}
# 修改字典中c的第一个元素,原列表同步变化
d1["c"][0] = 300
print(l1) # [300, 4, 5, 6]6.2 案例 2:字典嵌套字典
# 定义内层字典
d2 = {"x": 10, "y": 20}
# 定义外层字典,c键指向内层字典d2
d3 = {"a": 1, "b": 2, "c": d2}
# 向内层字典添加键值对,外层字典同步更新
d2["z"] = 30
print(d3) # {'a': 1, 'b': 2, 'c': {'x': 10, 'y': 20, 'z': 30}}
# 修改内层字典的x值(两种方式等价)
d3["c"].update({"x": 100})
print(d2) # {'x': 100, 'y': 20, 'z': 30}
# 重新赋值c键,断开与内层字典的引用
d3["c"] = 3
print(d3) # {'a': 1, 'b': 2, 'c': 3}6.3 案例 3:列表嵌套字典
# 定义基础字典
d4 = {"x": 10, "y": 20}
# 定义列表,第三个元素为字典d4
l2 = [1, 2, d4]
# 通过列表操作,删除字典d4中的y键
l2[2].pop("y")
print(d4) # {'x': 10}7. 实战:客户信息管理系统
7.1 案例 1:列表嵌套字典(按姓名操作)
# 初始化客户列表:列表中每个元素是【客户字典】
customers = [
{"name": "Alice", "age": 25, "email": "alice@example.com"},
{"name": "Bob", "age": 28, "email": "bob@example.com"}
]
# 无限循环,实现菜单功能
while True:
# 打印功能菜单
print("""
1. 添加客户
2. 删除客户
3. 修改客户
4. 查询一个客户
5. 查询所有客户
6. 退出
""")
# 获取用户输入的选项
choice = input("请输入您的选择:")
# 1. 添加客户
if choice == "1":
# 获取用户输入的客户信息
name = input("请输入添加客户的姓名:")
age = input("请输入添加客户的年龄:")
email = input("请输入添加客户的邮箱:")
# 封装为客户字典
new_customer = {"name": name, "age": age, "email": email}
# 添加到客户列表
customers.append(new_customer)
print(f"添加客户{name}成功!")
# 2. 删除客户
elif choice == "2":
del_name = input("请输入删除客户的姓名:")
flag = False # 标记是否找到客户
# 遍历客户列表
for customer in customers:
if customer["name"] == del_name:
customers.remove(customer)
print(f"客户{del_name}删除成功!")
flag = True
break
if not flag:
print(f"客户{del_name}不存在!")
# 3. 修改客户
elif choice == "3":
update_name = input("请输入修改客户的姓名:")
# 获取新信息
name = input("请输入新姓名:")
age = input("请输入新年龄:")
email = input("请输入新邮箱:")
# 遍历匹配并修改
for customer in customers:
if customer["name"] == update_name:
customer.update({"name": name, "age": age, "email": email})
break
print("客户信息修改完成!")
# 4. 查询单个客户
elif choice == "4":
query_name = input("请输入要查询的客户姓名:")
for customer in customers:
if customer["name"] == query_name:
print(f"姓名:{customer.get('name')},年龄:{customer.get('age')},邮箱:{customer.get('email')}")
break
# 5. 查询所有客户
elif choice == "5":
if customers:
for customer in customers:
print(f"姓名:{customer.get('name'):10},年龄:{customer.get('age')},邮箱:{customer.get('email')}")
else:
print("当前无客户信息!")
# 6. 退出程序
elif choice == "6":
print("退出程序!")
break
# 无效输入
else:
print("输入格式错误!")7.2 案例 2:字典嵌套字典(按 ID 操作,效率更高)
# 初始化:外层key=客户ID,value=客户字典(按ID查询更快)
customers = {
1001: {"name": "Alice", "age": 25, "email": "alice@example.com"},
1002: {"name": "Bob", "age": 28, "email": "bob@example.com"}
}
while True:
print("""
1. 添加客户
2. 删除客户
3. 修改客户
4. 查询一个客户
5. 查询所有客户
6. 退出
""")
choice = input("请输入您的选择:")
# 1. 添加客户
if choice == "1":
cid = int(input("请输入客户ID:"))
if cid in customers:
print("该ID已存在!")
else:
name = input("请输入姓名:")
age = input("请输入年龄:")
email = input("请输入邮箱:")
customers[cid] = {"name": name, "age": age, "email": email}
print(f"添加客户{name}成功!")
# 2. 删除客户(按ID删除,O(1)效率)
elif choice == "2":
cid = int(input("请输入删除的客户ID:"))
if cid in customers:
customers.pop(cid)
print(f"删除{cid}成功!")
else:
print("ID不存在!")
# 3. 修改客户
elif choice == "3":
cid = int(input("请输入修改的客户ID:"))
if cid in customers:
name = input("新姓名:")
age = input("新年龄:")
email = input("新邮箱:")
customers[cid].update({"name": name, "age": age, "email": email})
print(f"{cid}修改成功!")
else:
print("ID不存在!")
# 4. 查询单个客户
elif choice == "4":
cid = int(input("请输入查询的客户ID:"))
if cid in customers:
customer = customers[cid]
print(f"姓名:{customer.get('name')},年龄:{customer.get('age')},邮箱:{customer.get('email')}")
else:
print("ID不存在!")
# 5. 查询所有客户
elif choice == "5":
if customers:
for cid,customer in customers.items():
print(f"ID:{cid},姓名:{customer.get('name'):10},年龄:{customer.get('age')},邮箱:{customer.get('email')}")
else:
print("无客户信息!")
# 6. 退出
elif choice == "6":
print("退出程序!")
break
else:
print("输入错误!")