当前位置: 首页 > news >正文

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()

案例解析:

  1. 数据结构设计

    • 用外层字典users存储所有用户,键为唯一的“用户ID”,确保查询和删除的高效性。
    • 每个用户的详情用内层字典{"name": ..., "age": ..., "phone": ...}存储,便于按字段访问和修改。
  2. 核心功能实现

    • 添加用户:通过users[user_id] = {...}新增键值对,先检查ID是否已存在避免重复。
    • 查询用户:用users.get(user_id)安全查询,避免ID不存在时的KeyError
    • 修改用户:直接通过内层字典的键(如user["name"])更新值,支持部分字段修改。
    • 删除用户:用users.pop(user_id)删除并返回用户信息,提供反馈。
    • 显示所有用户:用users.items()遍历所有键值对,批量展示用户信息。
  3. 用户体验优化

    • 输入验证:检查年龄和手机号是否为数字,避免无效数据。
    • 容错处理:对不存在的用户ID提供友好提示,对空输入做兼容处理。
    • 操作反馈:每个操作后明确提示结果(如“添加成功”“删除成功”)。

八、字典使用的注意事项与最佳实践

  1. 键的选择

    • 优先使用字符串作为键:字符串语义清晰(如"name""age"),便于理解和维护。
    • 避免使用可变类型作为键:列表、字典等可变类型不能作为键,会抛出TypeError
    • 确保键的唯一性:重复键会被覆盖,导致数据丢失(添加时需先检查键是否存在)。
  2. 查询方式的选择

    • 已知键一定存在时,用dict[key]直接访问(简洁高效)。
    • 键可能不存在时,用dict.get(key, default)(安全,避免异常)。
  3. 遍历字典的最佳方式

    • 遍历键值对:for key, value in dict.items()(最常用,同时获取键和值)。
    • 仅遍历键:for key in dict(等同于for key in dict.keys(),简洁)。
    • 仅遍历值:for value in dict.values()(适合只关心值的场景)。
  4. 字典与列表的选择

    • 当需要“通过标识查找数据”(如按ID查用户)时,用字典(查询效率高)。
    • 当需要“按顺序存储数据”(如待办事项列表)时,用列表(有序且支持动态修改)。

九、总结

字典作为Python中键值对映射的数据结构,其核心特性和用法可归纳为:

  1. 核心特性

    • 键值对映射:通过唯一的不可变键快速访问值,查询效率高。
    • 灵活性:值可以是任意类型,支持嵌套字典表示复杂结构。
    • 可变性:支持新增、修改、删除键值对,动态调整数据。
  2. 核心操作

    • dict[key] = valuedict.setdefault(key, default)
    • del dict[key]dict.pop(key)dict.clear()
    • dict[key] = new_valuedict.update(other)
    • dict[key]dict.get(key)dict.keys()dict.values()dict.items()
  3. 典型应用场景

    • 存储关联数据(如用户信息、配置参数)。
    • 作为缓存(通过键快速查找值)。
    • 表示复杂结构(如JSON数据、嵌套分类)。
    • 统计与映射(如单词计数、ID与对象映射)。

掌握字典的使用是Python开发的基础,它在数据分析、Web开发、自动化脚本等领域都有广泛应用。灵活运用字典的特性和方法,能显著提高代码的简洁性和效率。

http://www.dtcms.com/a/394332.html

相关文章:

  • SpringCloudOAuth2+JWT:微服务统⼀认证方案
  • LeetCode 分类刷题:2517. 礼盒的最大甜蜜度
  • 深度学习优化器进阶:从SGD到AdamW,不同优化器的适用场景
  • C++ 之 【C++的IO流】
  • truffle学习笔记
  • 现代循环神经网络
  • vlc播放NV12原始视频数据
  • ThinkPHP8学习篇(七):数据库(三)
  • 链家租房数据爬虫与可视化项目 Python Scrapy+Django+Vue 租房数据分析可视化 机器学习 预测算法 聚类算法✅
  • MQTT协议知识点总结
  • C++ 类和对象·其一
  • TypeScript里的类型声明文件
  • 【LeetCode - 每日1题】设计电影租借系统
  • Java进阶教程,全面剖析Java多线程编程,线程安全,笔记12
  • DCC-GARCH模型与代码实现
  • 实验3掌握 Java 如何使用修饰符,方法中参数的传递,类的继承性以及类的多态性
  • 【本地持久化】功能-总结
  • 深入浅出现代FPU浮点乘法器设计
  • LinkedHashMap 访问顺序模式
  • 破解K个最近点问题的深度思考与通用解法
  • 链式结构的特性
  • 报表1-创建sql函数get_children_all
  • 9月20日 周六 农历七月廿九 哪些属相需要谨慎与调整?
  • godot实现tileMap地图
  • 【Unity+VSCode】NuGet包导入
  • QEMU虚拟机设置网卡模式为桥接,用xshell远程连接
  • Week 17: 深度学习补遗:Boosting和量子逻辑门
  • 【论文速递】2025年第13周(Mar-23-29)(Robotics/Embodied AI/LLM)
  • Webpack进阶配置
  • 【LeetCode 每日一题】3227. 字符串元音游戏