Python快速入门专业版(三十八):Python字典:键值对结构的增删改查与进阶用法
目录
- 引
- 一、字典的定义与特点:键值对的无序集合(Python 3.7+有序)
- 1. 基本创建方式
- 2. 键的合法性:不可变且唯一
- 3. 使用`dict()`函数创建
- 二、字典元素的增加:添加新的键值对
- 1. 直接赋值:`dict[key] = value`
- 2. `dict.setdefault(key, default)`:新增键并设置默认值
- 三、字典元素的删除:移除不需要的键值对
- 1. `del dict[key]`:删除指定键值对
- 2. `dict.pop(key, default)`:删除键值对并返回对应的值
- 3. `dict.clear()`:清空字典中所有键值对
- 四、字典元素的修改:更新已有键的值
- 1. 直接赋值修改:`dict[key] = new_value`
- 2. `dict.update(other)`:批量修改或新增键值对
- 五、字典元素的查询:获取键对应的值
- 1. 直接访问:`dict[key]`
- 2. `dict.get(key, default)`:安全访问(推荐)
- 3. 获取所有键、值、键值对
- 六、字典的进阶用法:嵌套字典与字典推导式
- 1. 嵌套字典:字典的值可以是字典
- 2. 字典推导式:快速创建字典
- 七、综合案例:字典实现用户信息管理系统
- 案例解析:
- 八、字典使用的注意事项与最佳实践
- 九、总结
引
字典(dictionary,简称dict)是Python中最灵活、最强大的数据结构之一,它通过键值对(key-value) 存储数据,能够根据“键”快速查找“值”,类似于现实世界中的字典(通过“单词”查找“释义”)。
本文将系统讲解字典的定义、键的特性、核心操作(增删改查),通过丰富的代码案例演示每个方法的使用场景,并最终实现一个“用户信息管理系统”综合案例,帮助你掌握字典在实际开发中的应用。
一、字典的定义与特点:键值对的无序集合(Python 3.7+有序)
字典是由大括号{}
包裹的键值对集合,每个键值对用逗号分隔,格式为{key1: value1, key2: value2, ...}
。其核心特点是:
- 键值对映射:通过唯一的“键”(key)访问对应的“值”(value),查找效率极高(平均时间复杂度为O(1))。
- 键的特性:键必须是不可变类型(如字符串、整数、元组),且在字典中唯一(重复键会被覆盖)。
- 值的特性:值可以是任意类型(整数、字符串、列表、字典等),且可以重复。
- 有序性:Python 3.7+版本中,字典会保留键值对的插入顺序(此前版本无序)。
1. 基本创建方式
# 1. 创建包含键值对的字典
person = {"name": "小明","age": 20,"gender": "男","is_student": True
}
print(person) # 输出:{'name': '小明', 'age': 20, 'gender': '男', 'is_student': True}# 2. 创建空字典(两种方式)
empty_dict1 = {}
empty_dict2 = dict()
print(empty_dict1, empty_dict2) # 输出:{} {}# 3. 用不同类型的键创建字典(键必须不可变)
mixed_keys = {1: "整数键","name": "字符串键",(1, 2): "元组键" # 元组是不可变的,可作为键
}
print(mixed_keys) # 输出:{1: '整数键', 'name': '字符串键', (1, 2): '元组键'}
2. 键的合法性:不可变且唯一
- 键必须不可变:列表等可变类型不能作为键,否则会抛出
TypeError
。 - 键必须唯一:重复的键会被最后出现的键值对覆盖。
# 错误:列表是可变类型,不能作为键
# invalid_dict = {[1, 2]: "值"} # 错误:TypeError: unhashable type: 'list'# 重复键会被覆盖
duplicate_keys = {"name": "小红", "name": "小李"}
print(duplicate_keys) # 输出:{'name': '小李'}(后出现的键值对覆盖前者)
3. 使用dict()
函数创建
dict()
函数可通过其他可迭代对象(如键值对列表、关键字参数)创建字典:
# 1. 通过键值对列表创建
list_to_dict = dict([("name", "小张"), ("age", 22)])
print(list_to_dict) # 输出:{'name': '小张', 'age': 22}# 2. 通过关键字参数创建(键必须是字符串,且无需引号)
kw_to_dict = dict(name="小王", age=21)
print(kw_to_dict) # 输出:{'name': '小王', 'age': 21}# 3. 通过两个列表(键列表和值列表)创建(使用zip()函数)
keys = ["name", "age"]
values = ["小李", 23]
zip_to_dict = dict(zip(keys, values))
print(zip_to_dict) # 输出:{'name': '小李', 'age': 23}
二、字典元素的增加:添加新的键值对
字典支持多种添加键值对的方式,最常用的是直接赋值和setdefault()
方法,适用于不同的场景。
1. 直接赋值:dict[key] = value
如果key
不存在于字典中,直接赋值会新增一个键值对;如果key
已存在,则会修改对应的值(详见“修改”部分)。
# 案例:向空字典添加键值对
user = {}
user["name"] = "小明" # 新增键"name"
user["age"] = 20 # 新增键"age"
user["hobbies"] = ["篮球", "游戏"] # 值可以是列表
print(user) # 输出:{'name': '小明', 'age': 20, 'hobbies': ['篮球', '游戏']}
2. dict.setdefault(key, default)
:新增键并设置默认值
setdefault()
方法有两个作用:
- 若
key
不存在,新增键值对key: default
,并返回default
。 - 若
key
已存在,不做任何修改,返回该键对应的现有值。
# 案例1:key不存在,新增键值对
person = {"name": "小李", "age": 22}
# 新增"gender"键,默认值为"男"
gender = person.setdefault("gender", "男")
print(person) # 输出:{'name': '小李', 'age': 22, 'gender': '男'}
print(gender) # 输出:男(返回默认值)# 案例2:key已存在,不修改
age = person.setdefault("age", 30) # "age"已存在,值保持22
print(person) # 输出:{'name': '小李', 'age': 22, 'gender': '男'}
print(age) # 输出:22(返回现有值)# 案例3:不指定default,默认值为None
address = person.setdefault("address")
print(person) # 输出:{'name': '小李', 'age': 22, 'gender': '男', 'address': None}
应用场景:setdefault()
适合在“不确定键是否存在”的情况下添加键值对,避免重复判断(如统计单词出现次数时,确保键已存在)。
三、字典元素的删除:移除不需要的键值对
字典提供了多种删除键值对的方法,包括del
语句、pop()
方法和clear()
方法,分别适用于不同的删除需求。
1. del dict[key]
:删除指定键值对
使用del
关键字可以删除字典中指定key
对应的键值对,若key
不存在,会抛出KeyError
。
person = {"name": "小明", "age": 20, "gender": "男"}# 删除"gender"键值对
del person["gender"]
print(person) # 输出:{'name': '小明', 'age': 20}# 删除不存在的键(报错)
# del person["address"] # 错误:KeyError: 'address'
2. dict.pop(key, default)
:删除键值对并返回对应的值
pop()
方法会删除指定key
对应的键值对,并返回该键的值;若key
不存在,返回指定的default
(不指定default
则抛出KeyError
)。
person = {"name": "小明", "age": 20, "gender": "男"}# 删除"age"键,返回对应的值
age = person.pop("age")
print(person) # 输出:{'name': '小明', 'gender': '男'}
print(age) # 输出:20# 删除不存在的键,指定默认值
address = person.pop("address", "未知")
print(address) # 输出:未知(返回默认值,不报错)# 删除不存在的键,不指定默认值(报错)
# person.pop("phone") # 错误:KeyError: 'phone'
应用场景:pop()
因能返回被删除的值,适合需要“取出并删除”键值对的场景(如从字典中提取并移除临时数据)。
3. dict.clear()
:清空字典中所有键值对
clear()
方法会删除字典中的所有键值对,使字典变为空字典(但字典对象本身仍存在)。
person = {"name": "小明", "age": 20}
person.clear() # 清空字典
print(person) # 输出:{}(空字典)
四、字典元素的修改:更新已有键的值
修改字典元素的核心是“通过键访问并重新赋值”,此外update()
方法可批量修改或新增键值对。
1. 直接赋值修改:dict[key] = new_value
如果key
已存在于字典中,直接赋值会更新该键对应的值。
person = {"name": "小明", "age": 20}# 修改"age"的值
person["age"] = 21
print(person) # 输出:{'name': '小明', 'age': 21}# 修改"name"的值
person["name"] = "大明"
print(person) # 输出:{'name': '大明', 'age': 21}
2. dict.update(other)
:批量修改或新增键值对
update()
方法接收另一个字典(或键值对迭代对象),将其中的键值对更新到当前字典中:
- 若键已存在,更新其值。
- 若键不存在,新增该键值对。
person = {"name": "小明", "age": 20}# 用另一个字典更新(修改age,新增gender)
person.update({"age": 21, "gender": "男"})
print(person) # 输出:{'name': '小明', 'age': 21, 'gender': '男'}# 用关键字参数更新(新增address)
person.update(address="北京市", phone="12345678")
print(person) # 输出:{'name': '小明', 'age': 21, 'gender': '男', 'address': '北京市', 'phone': '12345678'}
应用场景:update()
适合批量更新字典(如从表单或数据库获取多条数据后更新到字典)。
五、字典元素的查询:获取键对应的值
查询是字典最常用的操作之一,Python提供了多种查询方式,适应不同的需求(如直接访问、安全访问、获取所有键/值/键值对)。
1. 直接访问:dict[key]
通过key
直接访问对应的值,若key
不存在,会抛出KeyError
。
person = {"name": "小明", "age": 20, "gender": "男"}print(person["name"]) # 输出:小明
print(person["age"]) # 输出:20# 访问不存在的键(报错)
# print(person["address"]) # 错误:KeyError: 'address'
2. dict.get(key, default)
:安全访问(推荐)
get()
方法通过key
获取值,若key
不存在,返回指定的default
(不指定default
则返回None
),不会抛出异常,是更安全的查询方式。
person = {"name": "小明", "age": 20}# 获取存在的键
print(person.get("name")) # 输出:小明# 获取不存在的键,指定默认值
print(person.get("gender", "未知")) # 输出:未知# 获取不存在的键,不指定默认值(返回None)
print(person.get("address")) # 输出:None
最佳实践:在不确定键是否存在时,优先使用get()
方法,避免KeyError
导致程序崩溃。
3. 获取所有键、值、键值对
字典提供了三个方法用于获取整体数据:
dict.keys()
:返回所有键的视图(可迭代对象)。dict.values()
:返回所有值的视图。dict.items()
:返回所有键值对的视图(每个元素是(key, value)
元组)。
person = {"name": "小明", "age": 20, "gender": "男"}# 1. 获取所有键
keys = person.keys()
print(keys) # 输出:dict_keys(['name', 'age', 'gender'])
print(list(keys)) # 转换为列表:['name', 'age', 'gender']# 2. 获取所有值
values = person.values()
print(values) # 输出:dict_values(['小明', 20, '男'])
print(list(values)) # 转换为列表:['小明', 20, '男']# 3. 获取所有键值对
items = person.items()
print(items) # 输出:dict_items([('name', '小明'), ('age', 20), ('gender', '男')])
print(list(items)) # 转换为列表:[('name', '小明'), ('age', 20), ('gender', '男')]
应用场景:这些方法常用于遍历字典(如批量处理所有键值对):
# 遍历所有键值对(最常用)
for key, value in person.items():print(f"{key}: {value}")
# 输出:
# name: 小明
# age: 20
# gender: 男
六、字典的进阶用法:嵌套字典与字典推导式
1. 嵌套字典:字典的值可以是字典
当需要表示复杂结构的数据(如多级分类、嵌套信息)时,字典的值可以是另一个字典(嵌套字典)。
# 案例:用嵌套字典存储多个用户的详细信息
users = {"user1": {"name": "小明","age": 20,"contact": {"phone": "12345", "email": "xiaoming@example.com"}},"user2": {"name": "小红","age": 19,"contact": {"phone": "67890", "email": "xiaohong@example.com"}}
}# 访问嵌套字典中的值(多级索引)
print(users["user1"]["name"]) # 输出:小明
print(users["user2"]["contact"]["email"]) # 输出:xiaohong@example.com# 修改嵌套字典中的值
users["user1"]["age"] = 21
print(users["user1"]["age"]) # 输出:21
2. 字典推导式:快速创建字典
与列表推导式类似,字典推导式通过简洁的语法快速创建字典,格式为{key_expr: value_expr for item in iterable}
。
# 案例1:从列表创建字典(键为索引,值为列表元素)
fruits = ["apple", "banana", "orange"]
fruit_dict = {i: fruit for i, fruit in enumerate(fruits)}
print(fruit_dict) # 输出:{0: 'apple', 1: 'banana', 2: 'orange'}# 案例2:过滤并转换字典(保留值为偶数的键值对)
numbers = {"a": 1, "b": 2, "c": 3, "d": 4}
even_dict = {k: v for k, v in numbers.items() if v % 2 == 0}
print(even_dict) # 输出:{'b': 2, 'd': 4}# 案例3:交换键和值
original = {"name": "小明", "age": 20}
swapped = {v: k for k, v in original.items()}
print(swapped) # 输出:{'小明': 'name', 20: 'age'}
字典推导式使代码更简洁高效,适合从现有数据快速生成新字典。
七、综合案例:字典实现用户信息管理系统
结合字典的增删改查方法,实现一个用户信息管理系统,支持添加、查询、修改、删除用户信息(包含姓名、年龄、手机号)。
def user_management_system():"""用户信息管理系统:支持添加、查询、修改、删除用户"""# 用字典存储用户信息,键为用户ID,值为包含用户详情的字典users = {}print("=" * 60)print(" 用户信息管理系统")print("功能:")print("1. 添加用户(需输入ID、姓名、年龄、手机号)")print("2. 查询用户(按ID查询)")print("3. 修改用户信息(按ID修改)")print("4. 删除用户(按ID删除)")print("5. 显示所有用户")print("6. 退出")print("=" * 60)while True:choice = input("\n请选择功能(1-6):").strip()if choice == "1":# 1. 添加用户user_id = input("请输入用户ID:").strip()if user_id in users:print(f"错误:用户ID '{user_id}' 已存在")continuename = input("请输入姓名:").strip()age = input("请输入年龄:").strip()phone = input("请输入手机号:").strip()# 简单验证输入if not (name and age.isdigit() and phone.isdigit()):print("错误:输入格式无效(年龄和手机号必须是数字)")continue# 添加用户信息到字典users[user_id] = {"name": name,"age": int(age),"phone": phone}print(f"用户 '{user_id}' 添加成功")elif choice == "2":# 2. 查询用户if not users:print("暂无用户信息")continueuser_id = input("请输入要查询的用户ID:").strip()user = users.get(user_id) # 安全查询if user:print("\n" + "-" * 30)print(f"用户ID:{user_id}")print(f"姓名:{user['name']}")print(f"年龄:{user['age']}")print(f"手机号:{user['phone']}")print("-" * 30)else:print(f"未找到用户ID '{user_id}'")elif choice == "3":# 3. 修改用户信息if not users:print("暂无用户信息")continueuser_id = input("请输入要修改的用户ID:").strip()user = users.get(user_id)if not user:print(f"未找到用户ID '{user_id}'")continueprint("\n当前信息:")print(f"姓名:{user['name']},年龄:{user['age']},手机号:{user['phone']}")print("(直接回车表示不修改该字段)")# 逐个字段修改(支持部分修改)new_name = input("请输入新姓名:").strip()new_age = input("请输入新年龄:").strip()new_phone = input("请输入新手机号:").strip()# 更新非空输入的字段if new_name:user["name"] = new_nameif new_age and new_age.isdigit():user["age"] = int(new_age)if new_phone and new_phone.isdigit():user["phone"] = new_phoneprint(f"用户 '{user_id}' 信息修改成功")elif choice == "4":# 4. 删除用户if not users:print("暂无用户信息")continueuser_id = input("请输入要删除的用户ID:").strip()if user_id in users:# 弹出并删除用户信息deleted_user = users.pop(user_id)print(f"已删除用户 '{user_id}':{deleted_user}")else:print(f"未找到用户ID '{user_id}'")elif choice == "5":# 5. 显示所有用户if not users:print("暂无用户信息")continueprint("\n" + "=" * 40)print(f"共 {len(users)} 个用户:")for user_id, info in users.items():print(f"ID:{user_id},姓名:{info['name']},年龄:{info['age']},手机号:{info['phone']}")print("=" * 40)elif choice == "6":# 6. 退出print("系统已退出,再见!")breakelse:print("错误:请输入1-6之间的数字")# 运行用户信息管理系统
if __name__ == "__main__":user_management_system()
案例解析:
-
数据结构设计:
- 用外层字典
users
存储所有用户,键为唯一的“用户ID”,确保查询和删除的高效性。 - 每个用户的详情用内层字典
{"name": ..., "age": ..., "phone": ...}
存储,便于按字段访问和修改。
- 用外层字典
-
核心功能实现:
- 添加用户:通过
users[user_id] = {...}
新增键值对,先检查ID是否已存在避免重复。 - 查询用户:用
users.get(user_id)
安全查询,避免ID不存在时的KeyError
。 - 修改用户:直接通过内层字典的键(如
user["name"]
)更新值,支持部分字段修改。 - 删除用户:用
users.pop(user_id)
删除并返回用户信息,提供反馈。 - 显示所有用户:用
users.items()
遍历所有键值对,批量展示用户信息。
- 添加用户:通过
-
用户体验优化:
- 输入验证:检查年龄和手机号是否为数字,避免无效数据。
- 容错处理:对不存在的用户ID提供友好提示,对空输入做兼容处理。
- 操作反馈:每个操作后明确提示结果(如“添加成功”“删除成功”)。
八、字典使用的注意事项与最佳实践
-
键的选择:
- 优先使用字符串作为键:字符串语义清晰(如
"name"
、"age"
),便于理解和维护。 - 避免使用可变类型作为键:列表、字典等可变类型不能作为键,会抛出
TypeError
。 - 确保键的唯一性:重复键会被覆盖,导致数据丢失(添加时需先检查键是否存在)。
- 优先使用字符串作为键:字符串语义清晰(如
-
查询方式的选择:
- 已知键一定存在时,用
dict[key]
直接访问(简洁高效)。 - 键可能不存在时,用
dict.get(key, default)
(安全,避免异常)。
- 已知键一定存在时,用
-
遍历字典的最佳方式:
- 遍历键值对:
for key, value in dict.items()
(最常用,同时获取键和值)。 - 仅遍历键:
for key in dict
(等同于for key in dict.keys()
,简洁)。 - 仅遍历值:
for value in dict.values()
(适合只关心值的场景)。
- 遍历键值对:
-
字典与列表的选择:
- 当需要“通过标识查找数据”(如按ID查用户)时,用字典(查询效率高)。
- 当需要“按顺序存储数据”(如待办事项列表)时,用列表(有序且支持动态修改)。
九、总结
字典作为Python中键值对映射的数据结构,其核心特性和用法可归纳为:
-
核心特性:
- 键值对映射:通过唯一的不可变键快速访问值,查询效率高。
- 灵活性:值可以是任意类型,支持嵌套字典表示复杂结构。
- 可变性:支持新增、修改、删除键值对,动态调整数据。
-
核心操作:
- 增:
dict[key] = value
、dict.setdefault(key, default)
。 - 删:
del dict[key]
、dict.pop(key)
、dict.clear()
。 - 改:
dict[key] = new_value
、dict.update(other)
。 - 查:
dict[key]
、dict.get(key)
、dict.keys()
、dict.values()
、dict.items()
。
- 增:
-
典型应用场景:
- 存储关联数据(如用户信息、配置参数)。
- 作为缓存(通过键快速查找值)。
- 表示复杂结构(如JSON数据、嵌套分类)。
- 统计与映射(如单词计数、ID与对象映射)。
掌握字典的使用是Python开发的基础,它在数据分析、Web开发、自动化脚本等领域都有广泛应用。灵活运用字典的特性和方法,能显著提高代码的简洁性和效率。