上一篇我们学了列表和元组,它们都是“按位置存储数据”的序列结构——要获取元素,得记住索引或遍历查找。但实际开发中,更常见的需求是“通过一个标识找对应数据”(比如用姓名找成绩、用ID找用户信息),或是“快速去重、做数据对比”。这篇就来学能解决这两个需求的结构:字典(dict)和集合(set),搞懂它们,处理关联数据和去重需求会更高效。
一、先学字典(dict):按“键”找“值”的“映射容器”
字典是Python里最常用的“键值对映射结构”,就像一本“通讯录”——“姓名”是“键”(唯一标识),“电话”是“值”(对应数据),用大括号{}
表示,键和值用冒号:
分隔,键值对之间用逗号分隔。
1. 字典的创建:3种简单方式
# 方式1:直接用{}写键值对(键必须是“不可变类型”,比如字符串、数字、元组;值可以是任意类型)
student_dict = {
"name": "小明", # 键"name"对应值"小明"
"age": 18, # 键"age"对应值18
"score": 95, # 键"score"对应值95
"is_student": True
}
# 方式2:用dict()函数转换(适合从列表/元组生成字典)
list_to_dict = dict([("name", "小红"), ("age", 17)]) # 结果:{"name":"小红", "age":17}
# 方式3:用“键=值”的形式(键是字符串时可省略引号,简单场景常用)
simple_dict = dict(city="北京", area="海淀区") # 结果:{"city":"北京", "area":"海淀区"}
⚠️ 注意:字典的键必须唯一(重复的键会覆盖前面的值),且不能是列表、字典等“可变类型”(因为可变类型不能做唯一标识)。
2. 字典的核心操作:查、增、删、改
(1)查:通过“键”获取“值”
有两种常用方式,推荐用get()
(键不存在时不报错,更安全):
student_dict = {"name": "小明", "age": 18, "score": 95}
# 方式1:直接用“dict[键]”(键不存在会报错,慎用)
print(student_dict["name"]) # 结果:"小明"
# print(student_dict["gender"]) # 键"gender"不存在,会报错KeyError
# 方式2:用“dict.get(键, 默认值)”(键不存在时返回默认值,默认值可选)
print(student_dict.get("age")) # 结果:18(键存在,返回对应值)
print(student_dict.get("gender", "未知")) # 结果:"未知"(键不存在,返回默认值)
# 查所有键/值/键值对
print(student_dict.keys()) # 所有键:dict_keys(["name", "age", "score", "is_student"])
print(student_dict.values()) # 所有值:dict_values(["小明", 18, 95, True])
print(student_dict.items()) # 所有键值对:dict_items([("name","小明"), ("age",18), ...])
(2)增:添加新的键值对
直接用“dict[新键] = 新值”即可,若键已存在,会变成“改”操作:
student_dict = {"name": "小明", "age": 18}
# 添加新键值对(键"score"不存在)
student_dict["score"] = 95 # 结果:{"name":"小明", "age":18, "score":95}
# 键已存在(会覆盖旧值,相当于修改)
student_dict["age"] = 19 # 结果:{"name":"小明", "age":19, "score":95}
(3)删:删除键值对
常用del
(按键删)和pop()
(按键删,返回对应值):
student_dict = {"name": "小明", "age": 18, "score": 95}
# 方式1:del dict[键](键不存在会报错)
del student_dict["age"] # 结果:{"name":"小明", "score":95}
# 方式2:dict.pop(键, 默认值)(键不存在时返回默认值,不报错)
deleted_score = student_dict.pop("score", 0) # 返回95,结果:{"name":"小明"}
print(deleted_score) # 输出:95
(4)改:修改已有键的值
和“增”的语法一样——“dict[已存在的键] = 新值”:
student_dict = {"name": "小明", "score": 95}
student_dict["score"] = 98 # 键"score"已存在,修改为98
print(student_dict) # 结果:{"name":"小明", "score":98}
3. 字典的遍历:循环获取键值对
常用for
循环遍历键,再通过键取值;或直接遍历键值对:
student_dict = {"name": "小明", "age": 18, "score": 95}
# 方式1:遍历所有键,再取对应值
for key in student_dict:
print(f"{key}:{student_dict[key]}") # 输出:name:小明;age:18;score:95
# 方式2:用items()遍历键值对(更简洁)
for key, value in student_dict.items():
print(f"{key}:{value}") # 结果和上面一样
二、再学集合(set):无序、不重复的“数据容器”
集合是“无序且元素不重复”的结构,就像一个“去重篮”——往里放数据,自动去掉重复项,用大括号{}
表示(但没有键值对,和字典区分开),元素之间用逗号分隔。
1. 集合的创建:2种方式
# 方式1:直接用{}写元素(元素必须是不可变类型,且自动去重)
num_set = {1, 2, 3, 3, 4} # 重复的3会被去掉,结果:{1,2,3,4}
str_set = {"a", "b", "a"} # 重复的"a"会被去掉,结果:{"a","b"}
# 方式2:用set()函数转换(常用:把列表/元组转成集合,实现去重)
list_to_set = set([1, 2, 2, 3]) # 列表去重,结果:{1,2,3}
tuple_to_set = set(("x", "y", "x")) # 元组去重,结果:{"x","y"}
# 注意:创建空集合不能用{}({}是空字典),必须用set()
empty_set = set() # 正确:空集合
# empty_set = {} # 错误:空字典
⚠️ 注意:集合是无序的——获取元素时不能按索引,只能遍历或判断是否存在。
2. 集合的核心操作:去重、判断、数学运算
(1)去重:最常用的场景
把有重复元素的列表/元组转成集合,再转回列表/元组,就能快速去重:
# 列表去重案例
duplicate_list = [10, 20, 20, 30, 30, 30]
unique_list = list(set(duplicate_list)) # 先转集合去重,再转列表
print(unique_list) # 结果:[10,20,30](顺序可能变,因为集合无序)
(2)判断:元素是否在集合里(用in,比列表快)
集合判断元素是否存在的效率比列表高(尤其是数据量大时):
fruit_set = {"苹果", "香蕉", "橙子"}
print("苹果" in fruit_set) # 结果:True
print("葡萄" in fruit_set) # 结果:False
(3)数学运算:交集、并集、差集(数据对比常用)
假设有两个集合set1 = {1,2,3}
和set2 = {3,4,5}
,常用运算如下:
set1 = {1, 2, 3}
set2 = {3, 4, 5}
# 1. 交集:两个集合都有的元素(& 或 intersection())
print(set1 & set2) # 结果:{3}
print(set1.intersection(set2)) # 结果:{3}
# 2. 并集:两个集合所有的元素(去重)(| 或 union())
print(set1 | set2) # 结果:{1,2,3,4,5}
print(set1.union(set2)) # 结果:{1,2,3,4,5}
# 3. 差集:set1有但set2没有的元素(- 或 difference())
print(set1 - set2) # 结果:{1,2}
print(set1.difference(set2)) # 结果:{1,2}
3. 集合的增删:简单操作
fruit_set = {"苹果", "香蕉"}
# 增:add()(加单个元素)、update()(加多个元素,比如列表)
fruit_set.add("橙子") # 结果:{"苹果","香蕉","橙子"}
fruit_set.update(["葡萄", "芒果"]) # 结果:{"苹果","香蕉","橙子","葡萄","芒果"}
# 删:remove()(元素不存在会报错)、discard()(元素不存在不报错)
fruit_set.remove("香蕉") # 结果:{"苹果","橙子","葡萄","芒果"}
fruit_set.discard("西瓜") # 元素"西瓜"不存在,不报错,集合不变
三、关键对比:字典、集合与列表的核心区别
新手容易混淆这三种结构,记住核心差异,就能选对场景:
结构 | 语法符号 | 核心特性 | 适用场景 |
---|---|---|---|
列表 | [] | 有序、可重复、按索引找 | 存储需保留顺序的动态数据(如购物车) |
字典 | {key:value} | 无序、键唯一、按键找值 | 存储关联数据(如用户信息、成绩表) |
集合 | {} | 无序、不重复、高效判断 | 去重、数据对比(交集/并集) |
四、实战小案例:用字典和集合处理“学生成绩数据”
需求:有3个学生的成绩数据(含重复姓名),需要:1. 去重重复学生;2. 统计每个学生的平均分;3. 找出成绩≥90的学生。
# 原始数据:列表里的每个元素是(姓名,成绩)元组(含重复姓名)
score_data = [("小明", 95), ("小红", 88), ("小明", 92), ("小刚", 76), ("小红", 90)]
# 1. 用字典统计每个学生的成绩(去重姓名,键是姓名,值是成绩列表)
student_scores = {}
for name, score in score_data:
# 若姓名不在字典里,添加键,值为空列表;再把成绩加入列表
student_scores.setdefault(name, []).append(score)
print("每个学生的成绩:", student_scores) # 结果:{"小明":[95,92], "小红":[88,90], "小刚":[76]}
# 2. 计算每个学生的平均分,存入新字典
avg_scores = {}
for name, scores in student_scores.items():
avg = sum(scores) / len(scores) # 求和再除以成绩个数
avg_scores[name] = round(avg, 1) # 保留1位小数
print("每个学生的平均分:", avg_scores) # 结果:{"小明":93.5, "小红":89.0, "小刚":76.0}
# 3. 用集合找出平均分≥90的学生(去重,虽然这里没有重复,但演示集合用法)
excellent_students = set()
for name, avg in avg_scores.items():
if avg >= 90:
excellent_students.add(name)
print("平均分≥90的学生:", excellent_students) # 结果:{"小明"}
总结
这篇我们掌握了两种互补的数据结构:
- 字典(dict):
{key:value}
形式,按键找值,适合存储关联数据; - 集合(set):
{}
形式,无序不重复,适合去重和数据对比; - 核心区别:列表按索引、字典按键、集合按去重/判断,根据需求选结构。
到这里,Python基础语法和核心数据结构就学完了——下一篇我们会进入“函数与模块”的学习,把零散的代码封装成可复用的“工具”,让代码更简洁、更易维护~