01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来
01-【Python-Day 1】告别编程恐惧:轻松掌握 Python 安装与第一个程序的 6 个步骤
02-【Python-Day 2】掌握Python基石:变量、内存、标识符及int/float/bool数据类型
03-【Python-Day 3】玩转文本:字符串(String)基础操作详解 (上)
04-【Python-Day 4】玩转文本:Python 字符串常用方法深度解析 (下篇)
05-【Python-Day 5】Python 格式化输出实战:%、format()、f-string 对比与最佳实践
06- 【Python-Day 6】从零精通 Python 运算符(上):算术、赋值与比较运算全解析
07-【Python-Day 7】从零精通 Python 运算符(下):逻辑、成员、身份运算与优先级规则全解析
08-【Python-Day 8】从入门到精通:Python 条件判断 if-elif-else 语句全解析
09-【Python-Day 9】掌握循环利器:for 循环遍历序列与可迭代对象详解
10-【Python-Day 10】Python 循环控制流:while 循环详解与 for 循环对比
11-【Python-Day 11】列表入门:Python 中最灵活的数据容器 (创建、索引、切片)
12-【Python-Day 12】Python列表进阶:玩转添加、删除、排序与列表推导式
13-【Python-Day 13】Python 元组 (Tuple) 详解:从创建、操作到高级应用场景一网打尽
14-【Python-Day 14】玩转Python字典(上篇):从零开始学习创建、访问与操作
欢迎来到 Python 学习之旅的第 14 天!在之前的学习中,我们已经掌握了列表(List)和元组(Tuple)这两种强大的序列数据结构。今天,我们将踏入一个新的领域,探索 Python 中另一个至关重要且应用广泛的数据类型——字典(Dictionary)。字典以其独特的“键值对”存储方式,为我们提供了一种高效管理和查找数据的新途径。本篇作为字典详解的上篇,将重点带你入门字典的基础概念、创建方式以及核心的访问、添加、修改和删除操作。无论你是编程新手,还是希望巩固 Python 基础的开发者,本文都将为你打下坚实的字典基础。
想象一下我们现实生活中的字典,我们可以通过查找一个“词语”(键)来找到它的“释义”(值)。Python 中的字典与此类似,它是一个可变的、无序的(在 Python 3.7+ 版本中表现为有序)数据结构,用于存储一系列键值对 (key-value pairs)。
一个键和其对应的值构成一个键值对。字典就是这些键值对的集合。
字典是可变的,这意味着你可以在创建字典后,随时添加、删除或修改其中的键值对。
collections.OrderedDict
(尤其是在需要兼容旧版本或强调“有序”语义时)。但对于日常使用,Python 3.7+ 的内置 dict
已经足够。与列表或元组通过数字索引访问元素不同,字典中的值是通过其唯一的键来访问的。这种特性使得字典在根据特定标识符查找数据时非常高效。
想象你需要存储一个班级学生的信息,每个学生有学号和姓名。如果用列表,你可能需要两个列表(一个存学号,一个存姓名),或者一个嵌套列表,查找特定学号的学生姓名会比较麻烦。
使用字典,你可以将学号作为“键”,姓名作为“值”:
{'1001': '张三', '1002': '李四', '1003': '王五'}
这样,通过学号 ‘1001’ 就能迅速找到 ‘张三’。字典非常适合用于表示对象属性、配置信息、数据记录等场景。
Python 提供了多种创建字典的方式,下面我们来详细了解几种常用的方法。
{}
创建这是创建字典最常见和直接的方式。
如果你想先创建一个空的字典,之后再动态添加内容,可以这样做:
# 创建一个空字典
empty_dict = {}
print(f"这是一个空字典: {empty_dict}")
print(f"空字典的类型是: {type(empty_dict)}")
输出:
这是一个空字典: {}
空字典的类型是:
你可以在花括号内直接定义一系列的键值对,每个键值对之间用逗号 ,
分隔,键和值之间用冒号 :
分隔。
# 创建一个包含初始值的字典
student_info = {
"name": "小明",
"age": 18,
"major": "计算机科学",
"id": "S001"
}
print(f"学生信息字典: {student_info}")
contact_info = {"email": "[email protected]", "phone": "13800138000"}
print(f"联系方式字典: {contact_info}")
输出:
学生信息字典: {'name': '小明', 'age': 18, 'major': '计算机科学', 'id': 'S001'}
联系方式字典: {'email': '[email protected]', 'phone': '13800138000'}
dict()
构造函数创建dict()
构造函数提供了更灵活的字典创建方式。
你可以将键作为关键字参数传递给 dict()
函数,此时键必须是合法的 Python 标识符(通常是字符串,且不需要加引号)。
# 使用 dict() 构造函数和关键字参数创建字典
person = dict(name="小红", age=20, city="上海")
print(f"个人信息 (关键字参数创建): {person}")
输出:
个人信息 (关键字参数创建): {'name': '小红', 'age': 20, 'city': '上海'}
注意:这种方式下,键 name
, age
, city
自动成为字符串 “name”, “age”, “city”。
你可以将一个包含元组(或其他包含两个元素的可迭代对象)的列表或元组传递给 dict()
构造函数,每个元组代表一个键值对。
# 使用 dict() 构造函数和键值对序列创建字典
# 列表包含元组
items_list = [("apple", 5), ("banana", 3), ("orange", 7)]
fruit_stock = dict(items_list)
print(f"水果库存 (列表元组创建): {fruit_stock}")
# 元组包含元组
items_tuple = (("cpu", 2500), ("memory", 800), ("ssd", 600))
computer_parts = dict(items_tuple)
print(f"电脑配件 (元组元组创建): {computer_parts}")
输出:
水果库存 (列表元组创建): {'apple': 5, 'banana': 3, 'orange': 7}
电脑配件 (元组元组创建): {'cpu': 2500, 'memory': 800, 'ssd': 600}
虽然字典推导式(后续章节会讲)是更现代的方式,但 dict()
也可以接受一个“映射”对象。
例如,从两个列表创建字典(不常用,但可以了解):
keys = ["a", "b", "c"]
values = [1, 2, 3]
# 使用 zip 函数将键列表和值列表配对,然后传递给 dict()
my_dict_from_zip = dict(zip(keys, values))
print(f"通过zip创建的字典: {my_dict_from_zip}")
输出:
通过zip创建的字典: {'a': 1, 'b': 2, 'c': 3}
同样,dict()
不带任何参数时也会创建一个空字典:
empty_dict_constructor = dict()
print(f"使用 dict() 创建的空字典: {empty_dict_constructor}")
输出:
使用 dict() 创建的空字典: {}
字典的键非常重要,它们必须满足以下两个核心要求:
在一个字典中,所有的键必须是唯一的。如果你在定义字典时使用了重复的键,Python 不会报错,但只会保留最后一个键值对。
# 键的唯一性演示
duplicate_key_dict = {
"name": "张三",
"age": 25,
"name": "李四" # 重复的键 'name'
}
print(f"包含重复键的字典: {duplicate_key_dict}")
输出:
包含重复键的字典: {'name': '李四', 'age': 25}
可以看到,第一个 "name": "张三"
被后面的 "name": "李四"
覆盖了。
字典的键必须是不可变类型的对象,例如:
列表(list)、字典(dict)或者其他可变集合(set)不能作为字典的键,因为它们的值可以被修改,这会导致哈希值变化,破坏字典的内部结构。
简单来说,一个对象在其生命周期内,如果它的哈希值(通过 hash()
函数计算得到的一个整数)是不变的,并且可以与其他对象进行比较,那么这个对象就是可哈希的。不可变类型的对象通常都是可哈希的。
valid_keys_dict = {
"name": "Alice", # 字符串作为键
100: "ID Number", # 整数作为键
3.14: "PI", # 浮点数作为键
True: "Boolean Key", # 布尔值作为键
("host", "port"): "127.0.0.1:8080" # 元组作为键
}
print(f"包含各种合法键的字典: {valid_keys_dict}")
输出:
包含各种合法键的字典: {'name': 'Alice', 100: 'ID Number', 3.14: 'PI', True: 'Boolean Key', ('host', 'port'): '127.0.0.1:8080'}
尝试使用可变类型(如列表)作为键会导致 TypeError
。
# 尝试使用列表作为键 (会导致错误)
try:
invalid_key_dict = {
["my_list_key"]: "some value"
}
print(invalid_key_dict)
except TypeError as e:
print(f"错误信息: {e}")
输出:
错误信息: unhashable type: 'list'
这个错误明确告诉我们列表是不可哈希的,因此不能作为字典的键。
创建字典后,最常见的操作之一就是根据键来获取对应的值。
dict[key]
)你可以像访问列表元素那样,使用方括号 []
并在其中放入键来获取对应的值。
student = {"name": "小明", "age": 18, "major": "计算机科学"}
# 访问存在的键
student_name = student["name"]
student_age = student["age"]
print(f"学生姓名: {student_name}")
print(f"学生年龄: {student_age}")
输出:
学生姓名: 小明
学生年龄: 18
如果尝试访问一个字典中不存在的键,Python 会抛出 KeyError
异常。
student = {"name": "小明", "age": 18}
try:
student_gender = student["gender"] # "gender" 键不存在
print(f"学生性别: {student_gender}")
except KeyError as e:
print(f"访问不存在的键时发生错误: KeyError: {e}")
输出:
访问不存在的键时发生错误: KeyError: 'gender'
这种方式直接明了,但在不确定键是否存在时需要配合异常处理,否则可能导致程序中断。
get()
方法访问为了更安全地访问字典中的值(避免 KeyError
),可以使用字典的 get()
方法。
get(key)
的基本用法如果键存在,get(key)
返回对应的值;如果键不存在,它默认返回 None
,而不会抛出异常。
student = {"name": "小明", "age": 18}
# 访问存在的键
student_name = student.get("name")
print(f"学生姓名 (get): {student_name}")
# 访问不存在的键
student_gender = student.get("gender") # "gender" 键不存在
print(f"学生性别 (get, 键不存在): {student_gender}")
print(f"返回值的类型: {type(student_gender)}")
输出:
学生姓名 (get): 小明
学生性别 (get, 键不存在): None
返回值的类型:
get(key, default_value)
提供默认值get()
方法还可以接受第二个可选参数,作为当键不存在时返回的默认值。
student = {"name": "小明", "age": 18}
# 访问不存在的键,并提供一个默认值 "未知"
student_major = student.get("major", "未知")
print(f"学生专业 (get, 键不存在, 提供默认值): {student_major}")
# 访问存在的键,默认值不会被使用
student_age = student.get("age", 0) # age 存在,返回 18
print(f"学生年龄 (get, 键存在, 提供默认值): {student_age}")
输出:
学生专业 (get, 键不存在, 提供默认值): 未知
学生年龄 (get, 键存在, 提供默认值): 18
[]
vs get()
对比与选择特性 | dict[key] |
dict.get(key, default) |
---|---|---|
键存在时 | 返回对应的值 | 返回对应的值 |
键不存在时 | 抛出 KeyError 异常 |
返回 None (默认) 或指定的 default 值 |
适用场景 | 确定键一定存在,或希望通过异常处理错误 | 不确定键是否存在,希望避免异常,或提供优雅的默认处理 |
选择建议:
dict[key]
可能更合适,因为 KeyError
可以清晰地指示出问题。get()
方法是更好的选择。由于字典是可变的,我们可以很方便地向字典中添加新的键值对,或者修改已存在的键值对。操作方式非常相似。
如果指定的键在字典中不存在,那么赋值操作会向字典中添加一个新的键值对。
语法:dictionary[new_key] = value
# 初始字典
config = {"host": "localhost", "port": 8080}
print(f"初始配置: {config}")
# 添加新的键值对 "username"
config["username"] = "admin"
print(f"添加 username 后: {config}")
# 添加新的键值对 "timeout"
config["timeout"] = 30
print(f"添加 timeout 后: {config}")
输出:
初始配置: {'host': 'localhost', 'port': 8080}
添加 username 后: {'host': 'localhost', 'port': 8080, 'username': 'admin'}
添加 timeout 后: {'host': 'localhost', 'port': 8080, 'username': 'admin', 'timeout': 30}
如果指定的键在字典中已经存在,那么赋值操作会更新该键对应的值。
语法:dictionary[existing_key] = new_value
# 初始字典
user_profile = {"name": "张三", "email": "[email protected]", "status": "active"}
print(f"初始用户配置: {user_profile}")
# 修改 "email" 的值
user_profile["email"] = "[email protected]"
print(f"修改 email 后: {user_profile}")
# 修改 "status" 的值
user_profile["status"] = "inactive"
print(f"修改 status 后: {user_profile}")
输出:
初始用户配置: {'name': '张三', 'email': '[email protected]', 'status': 'active'}
修改 email 后: {'name': '张三', 'email': '[email protected]', 'status': 'active'}
修改 status 后: {'name': '张三', 'email': '[email protected]', 'status': 'inactive'}
总结:对于赋值操作 dictionary[key] = value
:
key
不存在于 dictionary
中,则添加新的键值对 key: value
。key
已存在于 dictionary
中,则更新 key
对应的 value
。Python 提供了几种从字典中删除键值对的方法。
pop()
方法删除pop(key[, default])
方法用于移除字典中指定的键值对,并返回该键对应的值。
pop(key)
基本用法如果键存在,则删除该键值对并返回其值。如果键不存在,则会引发 KeyError
。
car_specs = {"brand": "Tesla", "model": "Model S", "year": 2023, "color": "red"}
print(f"原始汽车规格: {car_specs}")
# 删除 "color" 键并获取其值
removed_color = car_specs.pop("color")
print(f"删除的颜色是: {removed_color}")
print(f"删除 color 后的规格: {car_specs}")
# 尝试删除一个存在的键 "year"
removed_year = car_specs.pop("year")
print(f"删除的年份是: {removed_year}")
print(f"删除 year 后的规格: {car_specs}")
输出:
原始汽车规格: {'brand': 'Tesla', 'model': 'Model S', 'year': 2023, 'color': 'red'}
删除的颜色是: red
删除 color 后的规格: {'brand': 'Tesla', 'model': 'Model S', 'year': 2023}
删除的年份是: 2023
删除 year 后的规格: {'brand': 'Tesla', 'model': 'Model S'}
pop(key, default)
提供默认值如果 pop()
方法提供了第二个参数 default
,那么当指定的键不存在时,不会抛出 KeyError
,而是返回这个 default
值,字典本身不会改变。
settings = {"theme": "dark", "fontSize": 14}
print(f"原始设置: {settings}")
# 尝试删除一个不存在的键 "language",并提供默认值
removed_lang = settings.pop("language", "english")
print(f"尝试删除 language 返回: {removed_lang}")
print(f"删除不存在的键后 (有默认值),设置不变: {settings}")
# 尝试删除存在的键 "fontSize",默认值不会被使用
removed_font_size = settings.pop("fontSize", 12)
print(f"删除 fontSize 返回: {removed_font_size}")
print(f"删除 fontSize 后: {settings}")
输出:
原始设置: {'theme': 'dark', 'fontSize': 14}
尝试删除 language 返回: english
删除不存在的键后 (有默认值),设置不变: {'theme': 'dark', 'fontSize': 14}
删除 fontSize 返回: 14
删除 fontSize 后: {'theme': 'dark'}
popitem()
方法删除popitem()
方法用于移除并返回字典中的一个“任意”键值对(以元组 (key, value)
的形式)。
popitem()
保证移除并返回最后插入的键值对 (LIFO - Last In, First Out)。如果字典为空,调用 popitem()
会引发 KeyError
。
# 适用于 Python 3.7+ (LIFO行为)
user_activity = {
"login_time": "2023-10-26 10:00",
"last_action": "view_profile",
"session_id": "xyz123" # 最后插入
}
print(f"原始用户活动: {user_activity}")
# 移除最后插入的项
last_item = user_activity.popitem()
print(f"移除的最后一项是: {last_item}")
print(f"popitem() 后用户活动: {user_activity}")
next_last_item = user_activity.popitem()
print(f"再次移除的最后一项是: {next_last_item}")
print(f"再次 popitem() 后用户活动: {user_activity}")
# 清空字典直至为空
user_activity.popitem()
# print(user_activity.popitem()) # 如果再调用,会引发 KeyError
输出 (Python 3.7+):
原始用户活动: {'login_time': '2023-10-26 10:00', 'last_action': 'view_profile', 'session_id': 'xyz123'}
移除的最后一项是: ('session_id', 'xyz123')
popitem() 后用户活动: {'login_time': '2023-10-26 10:00', 'last_action': 'view_profile'}
再次移除的最后一项是: ('last_action', 'view_profile')
再次 popitem() 后用户活动: {'login_time': '2023-10-26 10:00'}
del
关键字删除del
是 Python 的一个关键字(不是函数或方法),可以用来删除字典中指定的键值对。
语法:del dictionary[key]
如果指定的键不存在,del
会引发 KeyError
。
product = {"id": "P001", "name": "Laptop", "price": 7999, "in_stock": True}
print(f"原始产品信息: {product}")
# 删除 "in_stock" 键
del product["in_stock"]
print(f"删除 in_stock 后: {product}")
# 删除 "price" 键
del product["price"]
print(f"删除 price 后: {product}")
# 尝试删除不存在的键 (会导致 KeyError)
try:
del product["warranty"]
except KeyError as e:
print(f"尝试删除不存在的键 'warranty' 时发生错误: {e}")
输出:
原始产品信息: {'id': 'P001', 'name': 'Laptop', 'price': 7999, 'in_stock': True}
删除 in_stock 后: {'id': 'P001', 'name': 'Laptop', 'price': 7999}
删除 price 后: {'id': 'P001', 'name': 'Laptop'}
尝试删除不存在的键 'warranty' 时发生错误: 'warranty'
pop()
vs del
pop(key)
会删除键值对并返回被删除的值,适合你需要使用这个被删除值的场景。del dict[key]
直接删除键值对,不返回任何值。如果只是想删除,不在乎值是什么,del
更直接。在本篇【Python-Day 14】中,我们对 Python 字典(Dictionary)的基础知识进行了详细的探讨,主要集中在字典的创建与基本操作。以下是核心内容的概括:
什么是字典:
创建字典:
{}
:my_dict = {"key1": "value1", "key2": "value2"}
或 empty_dict = {}
。dict()
构造函数:
my_dict = dict(key1="value1", key2="value2")
。my_dict = dict([("key1", "value1"), ("key2", "value2")])
。zip()
函数结合键列表和值列表:my_dict = dict(zip(keys, values))
。键 (Key) 的要求:
访问字典中的值:
dict[key]
:如果键存在,返回对应的值;如果键不存在,抛出 KeyError
。get(key, default=None)
方法:如果键存在,返回对应的值;如果键不存在,返回 None
或指定的 default
值,不会报错。添加与修改键值对:
dictionary[key] = value
。key
不存在,则添加新的键值对。key
已存在,则修改该 key
对应的 value
。删除键值对:
pop(key[, default])
:删除指定 key
的键值对并返回其值。若 key
不存在且未提供 default
,则抛出 KeyError
。popitem()
:删除并返回一个键值对(Python 3.7+ 为最后插入的项)。字典为空时抛出 KeyError
。del dictionary[key]
:删除指定 key
的键值对。若 key
不存在,则抛出 KeyError
。通过本篇的学习,你已经掌握了字典最基本也是最常用的操作。在下一篇《字典 (Dictionary) 详解 (下)》中,我们将继续探索字典的常用方法(如获取所有键、值、遍历字典等)以及更高级的应用。敬请期待!