前言 本文将带你学习 Python 中的数据结构 ,包括列表 、元组 、字典 和集合 ,让你能够高效地存储和管理数据 !
在阅读过程中有任何问题都可以发布到评论区,有价值的问题将会放到文章末尾Q&A之中!
本文导航:
📦 数据结构概述:为什么需要数据结构
📋 列表 list:有序可变的数据集合
📌 元组 tuple:有序不可变的数据集合
📖 字典 dict:键值对映射的数据结构
🎯 集合 set:无序不重复的数据集合
🔄 数据结构对比:如何选择合适的数据结构
💡 实战练习:三个难度等级
⚠️ 常见错误:6大易错点
🚀 编程技巧:代码优化建议
数据结构概述 什么是数据结构 数据结构 是计算机中存储和组织数据的方式,就像现实生活中的各种容器:
📋 列表(list) - 像购物清单,有顺序,可以修改
📌 元组(tuple) - 像身份证号,有顺序,不能修改
📖 字典(dict) - 像通讯录,通过姓名查电话
🎯 集合(set) - 像抽奖箱,没有重复,没有顺序
为什么需要数据结构 没有数据结构时: 存储 5 个学生的成绩
1 2 3 4 5 student1_score = 85 student2_score = 92 student3_score = 78 student4_score = 90 student5_score = 88
如果有 100 个学生,就要定义 100 个变量!😱
有了数据结构后: 使用列表存储
1 2 scores = [85 , 92 , 78 , 90 , 88 ]
四种数据结构对比
数据结构
符号
是否有序
是否可变
是否重复
使用场景
列表 list
[]
✅ 有序
✅ 可变
✅ 可重复
存储一组相关数据
元组 tuple
()
✅ 有序
❌ 不可变
✅ 可重复
存储不应修改的数据
字典 dict
{}
❌ 无序*
✅ 可变
❌ 键不重复
键值对映射
集合 set
{}
❌ 无序
✅ 可变
❌ 不重复
去重、集合运算
*注:Python 3.7+ 字典保持插入顺序
列表 list 列表基础 列表(list) 是 Python 中最常用的数据结构,用于存储一组有序的数据。
列表的特点:
📝 有序 :元素有固定的顺序,可以通过索引访问
✏️ 可变 :可以修改、添加、删除元素
🔄 可重复 :可以包含重复的元素
🎨 类型灵活 :可以存储不同类型的数据
列表就像一个收纳盒:
盒子里可以放不同的东西(不同类型的数据)
每个东西都有固定的位置(索引)
可以随时添加或取出东西(可变)
可以放相同的东西(可重复)
创建列表 方式1:使用方括号 [] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 empty_list = [] print (empty_list) numbers = [1 , 2 , 3 , 4 , 5 ] print (numbers) mixed_list = [1 , "hello" , 3.14 , True ] print (mixed_list) nested_list = [[1 , 2 ], [3 , 4 ], [5 , 6 ]] print (nested_list)
方式2:使用 list() 函数 1 2 3 4 5 6 7 char_list = list ("Python" ) print (char_list) num_list = list (range (1 , 6 )) print (num_list)
方式3:使用循环创建列表 1 2 3 4 5 6 squares = [] for i in range (1 , 11 ): squares.append(i ** 2 ) print (squares)
访问列表元素 通过索引访问 列表的索引从 0 开始:
第 1 个元素的索引是 0
第 2 个元素的索引是 1
第 n 个元素的索引是 n-1
1 2 3 4 5 6 7 8 9 10 fruits = ["苹果" , "香蕉" , "橙子" , "葡萄" , "西瓜" ] print (fruits[0 ]) print (fruits[2 ]) print (fruits[4 ])
负索引访问 Python 支持负索引 ,从列表末尾开始计数:
-1 表示最后一个元素
-2 表示倒数第二个元素
-n 表示倒数第 n 个元素
1 2 3 4 5 6 7 8 9 10 fruits = ["苹果" , "香蕉" , "橙子" , "葡萄" , "西瓜" ] print (fruits[-1 ]) print (fruits[-2 ]) print (fruits[-5 ])
索引示意图 1 2 3 列表: ["苹果", "香蕉", "橙子", "葡萄", "西瓜"] 正索引: 0 1 2 3 4 负索引: -5 -4 -3 -2 -1
获取列表长度 1 2 3 4 5 6 7 8 9 fruits = ["苹果" , "香蕉" , "橙子" , "葡萄" , "西瓜" ] length = len (fruits) print (f"列表有 {length} 个元素" ) last_index = len (fruits) - 1 print (fruits[last_index])
修改列表元素 修改单个元素 1 2 3 4 5 6 7 8 9 10 numbers = [10 , 20 , 30 , 40 , 50 ] print ("修改前:" , numbers)numbers[0 ] = 100 print ("修改后:" , numbers) numbers[-1 ] = 500 print ("修改后:" , numbers)
添加元素 append() - 在末尾添加单个元素 1 2 3 4 5 6 7 8 9 fruits = ["苹果" , "香蕉" ] print ("添加前:" , fruits)fruits.append("橙子" ) print ("添加后:" , fruits) fruits.append("葡萄" ) print ("添加后:" , fruits)
insert() - 在指定位置插入元素 1 2 3 4 5 6 7 8 9 10 fruits = ["苹果" , "香蕉" , "橙子" ] print ("插入前:" , fruits)fruits.insert(1 , "西瓜" ) print ("插入后:" , fruits) fruits.insert(0 , "草莓" ) print ("插入后:" , fruits)
extend() - 添加多个元素 1 2 3 4 5 6 7 8 9 10 11 list1 = [1 , 2 , 3 ] list2 = [4 , 5 , 6 ] list1.extend(list2) print (list1) list3 = [7 , 8 ] list4 = list1 + list3 print (list4)
删除元素 remove() - 删除指定值的元素 1 2 3 4 5 6 fruits = ["苹果" , "香蕉" , "橙子" , "香蕉" , "葡萄" ] print ("删除前:" , fruits)fruits.remove("香蕉" ) print ("删除后:" , fruits)
pop() - 删除指定索引的元素 1 2 3 4 5 6 7 8 9 10 11 12 fruits = ["苹果" , "香蕉" , "橙子" , "葡萄" ] print ("删除前:" , fruits)last_fruit = fruits.pop() print ("删除的元素:" , last_fruit) print ("删除后:" , fruits) second_fruit = fruits.pop(1 ) print ("删除的元素:" , second_fruit) print ("删除后:" , fruits)
del - 删除元素或整个列表 1 2 3 4 5 6 7 8 9 numbers = [10 , 20 , 30 , 40 , 50 ] del numbers[2 ]print (numbers) del numbers
clear() - 清空列表 1 2 3 4 5 numbers = [1 , 2 , 3 , 4 , 5 ] print ("清空前:" , numbers)numbers.clear() print ("清空后:" , numbers)
列表常用方法 查找元素 index() - 查找元素的索引 1 2 3 4 5 6 7 8 9 fruits = ["苹果" , "香蕉" , "橙子" , "葡萄" , "香蕉" ] index = fruits.index("橙子" ) print (f"橙子的索引是:{index} " ) index = fruits.index("香蕉" ) print (f"香蕉的索引是:{index} " )
count() - 统计元素出现次数 1 2 3 4 5 6 7 8 numbers = [1 , 2 , 3 , 2 , 4 , 2 , 5 ] count = numbers.count(2 ) print (f"2 出现了 {count} 次" ) count = numbers.count(10 ) print (f"10 出现了 {count} 次" )
in - 判断元素是否存在 1 2 3 4 5 6 7 8 fruits = ["苹果" , "香蕉" , "橙子" ] if "香蕉" in fruits: print ("香蕉在列表中" ) if "葡萄" not in fruits: print ("葡萄不在列表中" )
排序和反转 sort() - 列表排序(修改原列表) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 numbers = [3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 ] print ("排序前:" , numbers)numbers.sort() print ("升序:" , numbers) numbers.sort(reverse=True ) print ("降序:" , numbers) fruits = ["橙子" , "苹果" , "香蕉" , "葡萄" ] fruits.sort() print (fruits)
sorted() - 返回新列表(不修改原列表) 1 2 3 4 5 6 7 numbers = [3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 ] print ("原列表:" , numbers)sorted_numbers = sorted (numbers) print ("排序后:" , sorted_numbers) print ("原列表:" , numbers)
reverse() - 反转列表 1 2 3 4 5 fruits = ["苹果" , "香蕉" , "橙子" , "葡萄" ] print ("反转前:" , fruits)fruits.reverse() print ("反转后:" , fruits)
复制列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 list1 = [1 , 2 , 3 ] list2 = list1.copy() list2[0 ] = 100 print ("list1:" , list1) print ("list2:" , list2) list3 = list1[:] list3[0 ] = 200 print ("list1:" , list1) print ("list3:" , list3)
注意 :直接赋值不会复制列表,而是创建引用!
1 2 3 4 5 6 list1 = [1 , 2 , 3 ] list2 = list1 list2[0 ] = 100 print ("list1:" , list1) print ("list2:" , list2)
列表切片 切片(Slicing) 是获取列表的一部分元素的操作。
语法格式: 列表[开始:结束:步长]
开始 :起始索引(包含),默认为 0
结束 :结束索引(不包含),默认为列表末尾
步长 :间隔,默认为 1
基本切片 1 2 3 4 5 6 7 8 9 10 11 12 13 numbers = [0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] print (numbers[2 :5 ]) print (numbers[:5 ]) print (numbers[5 :]) print (numbers[:])
带步长的切片 1 2 3 4 5 6 7 8 9 10 numbers = [0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] print (numbers[::2 ]) print (numbers[1 ::2 ]) print (numbers[::-1 ])
负索引切片 1 2 3 4 5 6 7 8 9 10 numbers = [0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] print (numbers[-3 :]) print (numbers[-5 :-1 ]) print (numbers[1 :-1 ])
切片应用示例 1 2 3 4 5 6 7 8 9 numbers = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] mid = len (numbers) // 2 first_half = numbers[:mid] second_half = numbers[mid:] print ("前一半:" , first_half) print ("后一半:" , second_half)
列表推导式 列表推导式(List Comprehension) 是一种简洁的创建列表的方式。
基本语法: [表达式 for 变量 in 序列]
带条件: [表达式 for 变量 in 序列 if 条件]
基本列表推导式 1 2 3 4 5 6 7 8 9 squares = [] for i in range (1 , 11 ): squares.append(i ** 2 ) print (squares)squares = [i ** 2 for i in range (1 , 11 )] print (squares)
带条件的列表推导式 1 2 3 4 5 6 7 evens = [i for i in range (1 , 21 ) if i % 2 == 0 ] print (evens) result = [i ** 2 for i in range (1 , 11 ) if i % 3 == 0 ] print (result)
字符串处理 1 2 3 4 5 6 7 8 9 fruits = ["apple" , "banana" , "orange" ] upper_fruits = [fruit.upper() for fruit in fruits] print (upper_fruits) words = ["hello" , "world" , "python" ] lengths = [len (word) for word in words] print (lengths)
嵌套列表推导式 1 2 3 4 5 6 7 8 9 matrix = [[i * 3 + j for j in range (1 , 4 )] for i in range (3 )] print (matrix)nested = [[1 , 2 ], [3 , 4 ], [5 , 6 ]] flat = [num for sublist in nested for num in sublist] print (flat)
列表实战应用 示例:成绩处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 print ("=== 成绩统计系统 ===" )scores = [85 , 92 , 78 , 90 , 88 , 76 , 95 , 82 , 89 , 91 ] print (f"总人数:{len (scores)} 人" )print (f"最高分:{max (scores)} 分" )print (f"最低分:{min (scores)} 分" )print (f"平均分:{sum (scores) / len (scores):.2 f} 分" )excellent = len ([s for s in scores if s >= 90 ]) good = len ([s for s in scores if 80 <= s < 90 ]) pass_count = len ([s for s in scores if 60 <= s < 80 ]) print (f"\n优秀(90+):{excellent} 人" )print (f"良好(80-89):{good} 人" )print (f"及格(60-79):{pass_count} 人" )
运行结果:
1 2 3 4 5 6 7 8 9 === 成绩统计系统 === 总人数:10 人 最高分:95 分 最低分:76 分 平均分:86.60 分 优秀(90+):4 人 良好(80-89):4 人 及格(60-79):2 人
元组 tuple 元组基础 元组(tuple) 是 Python 中的另一种序列类型,与列表类似,但有一个重要区别:元组是不可变的 。
元组的特点:
📝 有序 :元素有固定的顺序,可以通过索引访问
🔒 不可变 :创建后不能修改、添加、删除元素
🔄 可重复 :可以包含重复的元素
🎨 类型灵活 :可以存储不同类型的数据
元组就像一个密封的盒子:
盒子里装好东西后就被密封了(不可变)
可以看里面有什么(可访问)
但不能修改、添加或删除东西(不可变)
比普通盒子(列表)更安全、更高效
列表 vs 元组
特性
列表 list
元组 tuple
符号
[]
()
可变性
✅ 可变
❌ 不可变
修改元素
✅ 可以
❌ 不可以
添加元素
✅ 可以
❌ 不可以
删除元素
✅ 可以
❌ 不可以
性能
稍慢
更快
占用空间
稍大
更小
使用场景
需要修改的数据
不需要修改的数据
选择建议:
需要修改数据 → 使用列表
数据不需要修改 → 使用元组 (更安全、更快)
创建元组 方式1:使用圆括号 () 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 empty_tuple = () print (empty_tuple) print (type (empty_tuple)) numbers = (1 , 2 , 3 , 4 , 5 ) print (numbers) mixed_tuple = (1 , "hello" , 3.14 , True ) print (mixed_tuple) nested_tuple = ((1 , 2 ), (3 , 4 ), (5 , 6 )) print (nested_tuple)
方式2:不使用括号(逗号分隔) 1 2 3 4 5 6 7 8 coordinates = 10 , 20 , 30 print (coordinates) print (type (coordinates)) x, y = 100 , 200 print (x, y)
方式3:单个元素的元组 特别注意 :创建只有一个元素的元组时,必须在元素后面加逗号!
1 2 3 4 5 6 7 8 9 10 11 12 not_tuple = (5 ) print (type (not_tuple)) single_tuple = (5 ,) print (type (single_tuple)) print (single_tuple) single_tuple2 = 5 , print (type (single_tuple2))
方式4:使用 tuple() 函数 1 2 3 4 5 6 7 8 9 10 11 12 list_data = [1 , 2 , 3 , 4 , 5 ] tuple_data = tuple (list_data) print (tuple_data) char_tuple = tuple ("Python" ) print (char_tuple) num_tuple = tuple (range (1 , 6 )) print (num_tuple)
访问元组元素 通过索引访问 1 2 3 4 5 6 7 8 9 10 11 fruits = ("苹果" , "香蕉" , "橙子" , "葡萄" , "西瓜" ) print (fruits[0 ]) print (fruits[2 ]) print (fruits[4 ]) print (fruits[-1 ])
元组切片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 numbers = (0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) print (numbers[2 :5 ]) print (numbers[:5 ]) print (numbers[5 :]) print (numbers[::-1 ]) print (numbers[::2 ])
获取元组长度 1 2 3 4 5 fruits = ("苹果" , "香蕉" , "橙子" , "葡萄" ) length = len (fruits) print (f"元组有 {length} 个元素" )
元组的不可变性
不能修改元素 1 2 3 4 5 6 7 8 numbers = (1 , 2 , 3 , 4 , 5 ) try : numbers[0 ] = 100 except TypeError as e: print (f"错误:{e} " )
不能添加元素 1 2 3 4 5 6 7 fruits = ("苹果" , "香蕉" )
不能删除元素 1 2 3 4 5 6 7 8 numbers = (1 , 2 , 3 , 4 , 5 ) del numbers
元组拼接(创建新元组)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 tuple1 = (1 , 2 , 3 ) tuple2 = (4 , 5 , 6 ) tuple3 = tuple1 + tuple2 print (tuple3) tuple4 = tuple1 * 3 print (tuple4) print (tuple1) print (tuple2)
特殊情况:元组包含可变对象 重要 :元组本身不可变,但如果元组包含可变对象(如列表),可变对象的内容可以修改!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 tuple_with_list = (1 , 2 , [3 , 4 , 5 ]) print ("原元组:" , tuple_with_list)tuple_with_list[2 ][0 ] = 300 print ("修改后:" , tuple_with_list) tuple_with_list[2 ].append(6 ) print ("添加后:" , tuple_with_list)
元组常用方法 元组只有两个 方法:count() 和 index()
因为元组不可变,所以没有增删改的方法!
count() - 统计元素出现次数 1 2 3 4 5 6 7 8 9 numbers = (1 , 2 , 3 , 2 , 4 , 2 , 5 , 2 ) count = numbers.count(2 ) print (f"2 出现了 {count} 次" ) count = numbers.count(10 ) print (f"10 出现了 {count} 次" )
index() - 查找元素的索引 1 2 3 4 5 6 7 8 9 fruits = ("苹果" , "香蕉" , "橙子" , "葡萄" , "香蕉" ) index = fruits.index("橙子" ) print (f"橙子的索引是:{index} " ) index = fruits.index("香蕉" ) print (f"香蕉的索引是:{index} " )
in - 判断元素是否存在 1 2 3 4 5 6 7 8 fruits = ("苹果" , "香蕉" , "橙子" ) if "香蕉" in fruits: print ("香蕉在元组中" ) if "葡萄" not in fruits: print ("葡萄不在元组中" )
其他操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 numbers = (3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 ) print (f"最大值:{max (numbers)} " ) print (f"最小值:{min (numbers)} " ) print (f"总和:{sum (numbers)} " ) sorted_list = sorted (numbers) print (f"排序结果:{sorted_list} " ) print (f"类型:{type (sorted_list)} " ) sorted_tuple = tuple (sorted (numbers)) print (sorted_tuple)
元组解包 元组解包(Unpacking) 是一种将元组中的值分配给多个变量的操作。
基本解包 1 2 3 4 5 6 7 8 9 10 11 coordinates = (10 , 20 ) x, y = coordinates print (f"x = {x} , y = {y} " ) name, age, city = ("小明" , 18 , "北京" ) print (f"{name} ,{age} 岁,来自{city} " )
交换变量值 1 2 3 4 5 6 7 8 9 10 11 12 13 a = 10 b = 20 temp = a a = b b = temp print (f"a = {a} , b = {b} " ) a = 10 b = 20 a, b = b, a print (f"a = {a} , b = {b} " )
忽略某些值 1 2 3 4 5 6 7 8 9 person = ("小明" , 18 , "北京" , "学生" ) name, _, city, _ = person print (f"{name} 来自 {city} " ) name, age, *_ = person print (f"{name} , {age} 岁" )
使用 * 收集剩余值 1 2 3 4 5 6 7 8 9 10 11 12 13 numbers = (1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ) first, *middle, last = numbers print (f"第一个:{first} " ) print (f"中间:{middle} " ) print (f"最后一个:{last} " ) a, b, *rest = numbers print (f"a = {a} , b = {b} " ) print (f"rest = {rest} " )
函数返回多个值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 def get_student_info (): name = "小明" age = 18 score = 95 return name, age, score student_name, student_age, student_score = get_student_info() print (f"{student_name} ,{student_age} 岁,成绩{student_score} 分" )student_info = get_student_info() print (student_info)
遍历时解包 1 2 3 4 5 6 7 8 9 10 11 points = [(1 , 2 ), (3 , 4 ), (5 , 6 )] for x, y in points: print (f"坐标:({x} , {y} )" )
元组实战应用 示例:存储不可变的配置信息 1 2 3 4 5 6 7 8 9 10 DB_CONFIG = ("localhost" , 3306 , "mydb" , "root" , "password" ) host, port, database, username, password = DB_CONFIG print (f"连接数据库:{host} :{port} /{database} " )
元组的优势 为什么要使用元组?
安全性 🔒
性能 ⚡
可哈希 🔑
语义明确 📝
使用元组表示”这个数据不应该改变”
代码意图更清晰
1 2 3 4 5 6 7 8 9 10 11 locations = { (0 , 0 ): "原点" , (1 , 0 ): "右边" , (0 , 1 ): "上边" } print (locations[(0 , 0 )])
字典 dict 字典基础 字典(dict) 是 Python 中用于存储键值对(key-value pairs)的数据结构,也称为映射类型。
字典的特点:
🔑 键值对 :每个元素由键和值组成
📝 无序 *:元素没有固定顺序(Python 3.7+ 保持插入顺序)
✏️ 可变 :可以修改、添加、删除键值对
🎯 键唯一 :每个键只能出现一次,值可以重复
🚀 快速查找 :通过键快速访问值,时间复杂度 O(1)
*注:Python 3.7+ 字典保持插入顺序
字典就像一本通讯录:
姓名是键(key),电话是值(value)
通过姓名(键)快速找到电话(值)
每个人(键)只能有一个电话号码记录
可以添加、修改、删除联系人
为什么需要字典 没有字典时: 存储学生成绩
1 2 3 4 5 6 7 names = ["小明" , "小红" , "小刚" ] scores = [85 , 92 , 78 ] index = names.index("小红" ) print (f"小红的成绩:{scores[index]} " )
有了字典后:
1 2 3 4 5 6 7 8 9 student_scores = { "小明" : 85 , "小红" : 92 , "小刚" : 78 } print (f"小红的成绩:{student_scores['小红' ]} " )
创建字典 方式1:使用花括号 {} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 empty_dict = {} print (empty_dict) print (type (empty_dict)) student = { "name" : "小明" , "age" : 18 , "score" : 95 } print (student)mixed_dict = { "name" : "Python" , "version" : 3.9 , "is_free" : True , "features" : ["simple" , "powerful" ] } print (mixed_dict)
方式2:使用 dict() 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 person = dict (name="小明" , age=18 , city="北京" ) print (person)pairs = [("a" , 1 ), ("b" , 2 ), ("c" , 3 )] dict_from_pairs = dict (pairs) print (dict_from_pairs)keys = ["name" , "age" , "city" ] values = ["小红" , 20 , "上海" ] person2 = dict (zip (keys, values)) print (person2)
方式3:使用 fromkeys() 创建 1 2 3 4 5 6 7 8 9 10 11 keys = ["a" , "b" , "c" ] default_dict = dict .fromkeys(keys, 0 ) print (default_dict)subjects = ["语文" , "数学" , "英语" ] scores = dict .fromkeys(subjects) print (scores)
访问字典元素 使用方括号访问 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 student = { "name" : "小明" , "age" : 18 , "score" : 95 , "city" : "北京" } print (student["name" ]) print (student["score" ]) try : print (student["grade" ]) except KeyError as e: print (f"错误:键 {e} 不存在" )
使用 get() 方法(推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 student = { "name" : "小明" , "age" : 18 , "score" : 95 } print (student.get("name" )) print (student.get("score" )) print (student.get("grade" )) print (student.get("grade" , "未知" )) print (student.get("city" , "北京" ))
检查键是否存在 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 student = { "name" : "小明" , "age" : 18 } if "name" in student: print ("name 键存在" ) if "score" not in student: print ("score 键不存在" ) print (student.keys()) print (student.values()) print (student.items())
修改字典元素 修改已有键的值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 student = { "name" : "小明" , "age" : 18 , "score" : 85 } print ("修改前:" , student)student["age" ] = 19 student["score" ] = 95 print ("修改后:" , student)
添加新键值对 1 2 3 4 5 6 7 8 9 10 11 12 13 student = { "name" : "小明" , "age" : 18 } print ("添加前:" , student)student["score" ] = 95 student["city" ] = "北京" print ("添加后:" , student)
删除键值对 del - 删除指定键 1 2 3 4 5 6 7 8 9 10 11 12 13 14 student = { "name" : "小明" , "age" : 18 , "score" : 95 , "city" : "北京" } del student["city" ]print (student)
pop() - 删除并返回值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 student = { "name" : "小明" , "age" : 18 , "score" : 95 } score = student.pop("score" ) print (f"删除的成绩:{score} " ) print (student) city = student.pop("city" , "未知" ) print (f"城市:{city} " )
popitem() - 删除最后一个键值对 1 2 3 4 5 6 7 8 9 10 student = { "name" : "小明" , "age" : 18 , "score" : 95 } last_item = student.popitem() print (f"删除的项:{last_item} " ) print (student)
clear() - 清空字典 1 2 3 4 5 6 7 8 student = { "name" : "小明" , "age" : 18 , "score" : 95 } student.clear() print (student)
字典常用方法 update() - 合并字典 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dict1 = {"a" : 1 , "b" : 2 } dict2 = {"c" : 3 , "d" : 4 } dict1.update(dict2) print (dict1)dict3 = {"name" : "小明" , "age" : 18 } dict4 = {"age" : 19 , "city" : "北京" } dict3.update(dict4) print (dict3)
setdefault() - 获取值或设置默认值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 student = { "name" : "小明" , "age" : 18 } name = student.setdefault("name" , "未知" ) print (name) score = student.setdefault("score" , 0 ) print (score) print (student)
copy() - 浅拷贝字典 1 2 3 4 5 6 7 8 original = {"a" : 1 , "b" : 2 , "c" : 3 } copied = original.copy() copied["a" ] = 100 print ("原字典:" , original) print ("拷贝后:" , copied)
注意 :直接赋值不会复制字典,而是创建引用!
1 2 3 4 5 6 dict1 = {"a" : 1 , "b" : 2 } dict2 = dict1 dict2["a" ] = 100 print ("dict1:" , dict1) print ("dict2:" , dict2)
字典遍历 遍历键 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 student = { "name" : "小明" , "age" : 18 , "score" : 95 } print ("=== 方式1 ===" )for key in student: print (f"{key} : {student[key]} " ) print ("\n=== 方式2 ===" )for key in student.keys(): print (f"{key} : {student[key]} " )
遍历值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 student = { "name" : "小明" , "age" : 18 , "score" : 95 } for value in student.values(): print (value)
遍历键值对(推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 student = { "name" : "小明" , "age" : 18 , "score" : 95 } for key, value in student.items(): print (f"{key} : {value} " )
遍历示例:成绩统计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 scores = { "小明" : 85 , "小红" : 92 , "小刚" : 78 , "小丽" : 95 , "小华" : 88 } print ("=== 学生成绩 ===" )total = 0 for name, score in scores.items(): print (f"{name} :{score} 分" , end="" ) if score >= 90 : print (" [优秀]" ) elif score >= 80 : print (" [良好]" ) elif score >= 60 : print (" [及格]" ) else : print (" [不及格]" ) total += score average = total / len (scores) print (f"\n平均分:{average:.2 f} " )
字典推导式 字典推导式(Dict Comprehension) 是一种简洁的创建字典的方式。
基本语法: {键表达式: 值表达式 for 变量 in 序列}
带条件: {键表达式: 值表达式 for 变量 in 序列 if 条件}
基本字典推导式 1 2 3 4 5 6 7 8 9 10 squares = {x: x**2 for x in range (1 , 6 )} print (squares)fruits = ["苹果" , "香蕉" , "橙子" ] fruit_dict = {fruit: len (fruit) for fruit in fruits} print (fruit_dict)
带条件的字典推导式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 numbers = {x: x**2 for x in range (1 , 11 ) if x % 2 == 0 } print (numbers)all_scores = { "小明" : 85 , "小红" : 92 , "小刚" : 78 , "小丽" : 95 } good_scores = {name: score for name, score in all_scores.items() if score > 80 } print (good_scores)
交换键值 1 2 3 4 5 6 7 original = {"a" : 1 , "b" : 2 , "c" : 3 } swapped = {value: key for key, value in original.items()} print (swapped)
字符串处理 1 2 3 4 5 6 7 8 9 10 11 12 13 text = "hello" char_count = {char: text.count(char) for char in text} print (char_count)text = "hello world" char_count = {} for char in text: char_count[char] = char_count.get(char, 0 ) + 1 print (char_count)
字典实战应用 示例:学生信息管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 students = { "S001" : { "name" : "小明" , "age" : 18 , "score" : 85 }, "S002" : { "name" : "小红" , "age" : 19 , "score" : 92 }, "S003" : { "name" : "小刚" , "age" : 18 , "score" : 78 } } print ("=== 学生信息表 ===" )for student_id, info in students.items(): print (f"\n学号:{student_id} " ) print (f" 姓名:{info['name' ]} " ) print (f" 年龄:{info['age' ]} 岁" ) print (f" 成绩:{info['score' ]} 分" )
集合 set 集合基础 集合(set) 是 Python 中用于存储不重复元素的无序数据结构。
集合的特点:
🎯 无序 :元素没有固定顺序,不能通过索引访问
✨ 唯一 :自动去除重复元素,每个元素只出现一次
✏️ 可变 :可以添加、删除元素
🚀 快速查找 :判断元素是否存在的速度很快,时间复杂度 O(1)
🔑 可哈希 :集合本身不可哈希,但元素必须是可哈希的
集合就像抽奖箱:
每个号码(元素)只有一个,不会重复
号码之间没有顺序
可以随时添加或取出号码
快速查找某个号码是否存在
为什么需要集合 没有集合时: 去除列表中的重复元素
1 2 3 4 5 6 7 8 9 numbers = [1 , 2 , 3 , 2 , 4 , 3 , 5 , 1 ] unique = [] for num in numbers: if num not in unique: unique.append(num) print (unique)
有了集合后:
1 2 3 4 numbers = [1 , 2 , 3 , 2 , 4 , 3 , 5 , 1 ] unique = list (set (numbers)) print (unique)
创建集合 方式1:使用花括号 {} 1 2 3 4 5 6 7 8 9 10 11 12 fruits = {"苹果" , "香蕉" , "橙子" } print (fruits) print (type (fruits)) numbers = {1 , 2 , 3 , 2 , 4 , 3 , 5 , 1 } print (numbers) valid_set = {1 , "hello" , 3.14 , True , (1 , 2 )} print (valid_set)
注意 :不能用 {} 创建空集合,因为 {} 会创建空字典!
1 2 3 4 5 6 7 empty = {} print (type (empty)) empty_set = set () print (type (empty_set))
方式2:使用 set() 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 list_data = [1 , 2 , 3 , 2 , 4 , 3 , 5 ] set_from_list = set (list_data) print (set_from_list) char_set = set ("hello" ) print (char_set) tuple_data = (1 , 2 , 3 , 2 , 4 ) set_from_tuple = set (tuple_data) print (set_from_tuple)
集合不能包含可变元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 valid_set = {1 , 2 , "hello" , (1 , 2 ), True } print (valid_set)try : invalid_set = {1 , 2 , [3 , 4 ]} except TypeError as e: print (f"错误:{e} " ) try : invalid_set = {1 , 2 , {"a" : 1 }} except TypeError as e: print (f"错误:{e} " )
访问集合元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fruits = {"苹果" , "香蕉" , "橙子" } for fruit in fruits: print (fruit) if "苹果" in fruits: print ("苹果在集合中" ) if "葡萄" not in fruits: print ("葡萄不在集合中" ) print (f"集合有 {len (fruits)} 个元素" )
集合常用方法 添加元素 add() - 添加单个元素 1 2 3 4 5 6 7 8 9 10 fruits = {"苹果" , "香蕉" } print ("添加前:" , fruits)fruits.add("橙子" ) print ("添加后:" , fruits) fruits.add("苹果" ) print ("再次添加:" , fruits)
update() - 添加多个元素 1 2 3 4 5 6 7 8 9 10 11 12 fruits = {"苹果" , "香蕉" } print ("添加前:" , fruits)fruits.update(["橙子" , "葡萄" , "西瓜" ]) print ("添加后:" , fruits)more_fruits = {"猕猴桃" , "芒果" } fruits.update(more_fruits) print ("继续添加:" , fruits)
删除元素 remove() - 删除指定元素(不存在会报错) 1 2 3 4 5 6 7 8 9 10 11 12 13 fruits = {"苹果" , "香蕉" , "橙子" } print ("删除前:" , fruits)fruits.remove("香蕉" ) print ("删除后:" , fruits) try : fruits.remove("葡萄" ) except KeyError as e: print (f"错误:{e} " )
discard() - 删除指定元素(不存在不报错) 1 2 3 4 5 6 7 8 9 10 fruits = {"苹果" , "香蕉" , "橙子" } print ("删除前:" , fruits)fruits.discard("香蕉" ) print ("删除后:" , fruits) fruits.discard("葡萄" ) print ("再次删除:" , fruits)
pop() - 随机删除并返回一个元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 fruits = {"苹果" , "香蕉" , "橙子" } print ("删除前:" , fruits)removed = fruits.pop() print (f"删除的元素:{removed} " )print ("删除后:" , fruits)empty_set = set () try : empty_set.pop() except KeyError: print ("错误:空集合无法 pop" )
clear() - 清空集合 1 2 3 4 5 fruits = {"苹果" , "香蕉" , "橙子" } print ("清空前:" , fruits)fruits.clear() print ("清空后:" , fruits)
集合运算 集合支持数学上的集合运算:并集、交集、差集、对称差集
并集 (Union) - 所有元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 set1 = {1 , 2 , 3 , 4 } set2 = {3 , 4 , 5 , 6 } union1 = set1 | set2 print ("并集(|):" , union1) union2 = set1.union(set2) print ("并集(union):" , union2) set3 = {7 , 8 } union3 = set1 | set2 | set3 print ("多个并集:" , union3)
交集 (Intersection) - 共有元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 set1 = {1 , 2 , 3 , 4 } set2 = {3 , 4 , 5 , 6 } intersection1 = set1 & set2 print ("交集(&):" , intersection1) intersection2 = set1.intersection(set2) print ("交集(intersection):" , intersection2) set3 = {3 , 4 , 7 , 8 } intersection3 = set1 & set2 & set3 print ("多个交集:" , intersection3)
差集 (Difference) - 在A中但不在B中 1 2 3 4 5 6 7 8 9 10 11 12 13 set1 = {1 , 2 , 3 , 4 } set2 = {3 , 4 , 5 , 6 } diff1 = set1 - set2 print ("差集(set1 - set2):" , diff1) diff2 = set2 - set1 print ("差集(set2 - set1):" , diff2) diff3 = set1.difference(set2) print ("差集(difference):" , diff3)
对称差集 (Symmetric Difference) - 不共有的元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 set1 = {1 , 2 , 3 , 4 } set2 = {3 , 4 , 5 , 6 } sym_diff1 = set1 ^ set2 print ("对称差集(^):" , sym_diff1) sym_diff2 = set1.symmetric_difference(set2) print ("对称差集(symmetric_difference):" , sym_diff2) sym_diff3 = (set1 - set2) | (set2 - set1) print ("等价写法:" , sym_diff3)
集合运算总结
运算
运算符
方法
说明
并集
|
union()
A 或 B 中的所有元素
交集
&
intersection()
A 和 B 共有的元素
差集
-
difference()
在 A 中但不在 B 中
对称差集
^
symmetric_difference()
在 A 或 B 中但不同时在两者中
集合关系判断 issubset() - 是否是子集 1 2 3 4 5 6 7 8 9 10 set1 = {1 , 2 , 3 } set2 = {1 , 2 , 3 , 4 , 5 } set3 = {1 , 2 , 6 } print (set1.issubset(set2)) print (set1 <= set2) print (set1.issubset(set3))
issuperset() - 是否是超集 1 2 3 4 5 6 set1 = {1 , 2 , 3 , 4 , 5 } set2 = {1 , 2 , 3 } print (set1.issuperset(set2)) print (set1 >= set2)
isdisjoint() - 是否没有交集 1 2 3 4 5 6 7 8 9 set1 = {1 , 2 , 3 } set2 = {4 , 5 , 6 } set3 = {3 , 4 , 5 } print (set1.isdisjoint(set2)) print (set1.isdisjoint(set3))
集合推导式 集合推导式(Set Comprehension) 是一种简洁的创建集合的方式。
基本语法: {表达式 for 变量 in 序列}
带条件: {表达式 for 变量 in 序列 if 条件}
基本集合推导式 1 2 3 4 5 6 7 8 9 squares = {x**2 for x in range (1 , 11 )} print (squares)chars = {c.upper() for c in "hello" } print (chars)
带条件的集合推导式 1 2 3 4 5 6 7 8 9 evens = {x for x in range (1 , 21 ) if x % 2 == 0 } print (evens)multiples_of_3 = {x**2 for x in range (1 , 11 ) if x % 3 == 0 } print (multiples_of_3)
去重应用 1 2 3 4 5 6 7 8 9 10 11 numbers = [1 , 2 , 3 , 2 , 4 , 3 , 5 , 1 , 4 ] unique_numbers = {x for x in numbers} print (unique_numbers)text = "hello world" unique_chars = {c for c in text if c != ' ' } print (unique_chars)
集合实战应用 示例:去除重复数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def remove_duplicates (data ): """去除列表中的重复元素""" return list (set (data)) numbers = [1 , 2 , 3 , 2 , 4 , 3 , 5 , 1 , 4 , 5 ] unique = remove_duplicates(numbers) print (f"原列表:{numbers} " )print (f"去重后:{unique} " )def remove_duplicates_ordered (data ): """去重但保持原顺序""" seen = set () result = [] for item in data: if item not in seen: seen.add(item) result.append(item) return result unique_ordered = remove_duplicates_ordered(numbers) print (f"保持顺序去重:{unique_ordered} " )
集合性能优势 集合在某些操作上比列表更快!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import timelarge_list = list (range (100000 )) large_set = set (range (100000 )) search_value = 99999 start = time.time() result = search_value in large_list list_time = time.time() - start start = time.time() result = search_value in large_set set_time = time.time() - start print (f"列表查找耗时:{list_time:.6 f} 秒" )print (f"集合查找耗时:{set_time:.6 f} 秒" )print (f"集合比列表快 {list_time/set_time:.2 f} 倍" )
性能对比:
查找元素 :集合 O(1) vs 列表 O(n)
去重 :集合自动去重
集合运算 :集合直接支持,列表需要遍历
何时使用集合:
✅ 需要去重
✅ 需要频繁判断元素是否存在
✅ 需要进行集合运算(交集、并集等)
✅ 不关心元素顺序
何时不用集合:
❌ 需要保持元素顺序
❌ 需要通过索引访问
❌ 元素需要可变(如列表、字典)
❌ 需要重复元素
数据结构选择指南 如何选择数据结构 选择数据结构的关键问题:
📝 需要保持顺序吗?
🔒 数据会被修改吗?
🔑 需要通过键访问值吗?
✨ 允许重复元素吗?
四种数据结构对比表
特性
列表 list
元组 tuple
字典 dict
集合 set
符号
[]
()
{}
{} / set()
有序
✅ 是
✅ 是
❌ 无序*
❌ 无序
可变
✅ 可变
❌ 不可变
✅ 可变
✅ 可变
重复
✅ 可重复
✅ 可重复
❌ 键不重复
❌ 不重复
索引访问
✅ 支持
✅ 支持
❌ 不支持
❌ 不支持
键值对
❌ 否
❌ 否
✅ 是
❌ 否
查找速度
O(n)
O(n)
O(1)
O(1)
使用场景
需要修改的序列
不需修改的序列
键值映射
去重、集合运算
*注:Python 3.7+ 字典保持插入顺序
选择决策树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if 需要存储键值对: 使用字典 dict elif 需要去重 or 需要集合运算: 使用集合 set elif 数据不会改变: if 需要作为字典的键: 使用元组 tuple else : 使用元组 tuple (更安全、更快) else : 使用列表 list
实际应用场景 列表 (list) 的应用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 scores = [85 , 92 , 78 , 90 , 88 ] shopping_list = ["苹果" , "香蕉" ] shopping_list.append("橙子" ) first_item = shopping_list[0 ] numbers = [3 , 1 , 4 , 1 , 5 ] numbers.sort() votes = ["A" , "B" , "A" , "C" , "A" ]
元组 (tuple) 的应用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def get_user_info (): return ("小明" , 18 , "北京" ) locations = { (0 , 0 ): "原点" , (1 , 0 ): "右边" } DATABASE_CONFIG = ("localhost" , 3306 , "mydb" ) WEEK_DAYS = ("周一" , "周二" , "周三" , "周四" , "周五" , "周六" , "周日" ) coordinates = (10 , 20 )
字典 (dict) 的应用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 student_scores = { "小明" : 85 , "小红" : 92 , "小刚" : 78 } config = { "host" : "localhost" , "port" : 8080 , "debug" : True } word_count = {} for word in text.split(): word_count[word] = word_count.get(word, 0 ) + 1 cache = {} if key in cache: return cache[key] user_data = { "name" : "小明" , "age" : 18 , "hobbies" : ["编程" , "阅读" ] }
集合 (set) 的应用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 numbers = [1 , 2 , 3 , 2 , 4 , 3 , 5 ] unique_numbers = list (set (numbers)) valid_users = {"user1" , "user2" , "user3" } if username in valid_users: login() set1 = {1 , 2 , 3 , 4 } set2 = {3 , 4 , 5 , 6 } common = set1 & set2 xiaoming_friends = {"小红" , "小刚" , "小丽" } xiaohong_friends = {"小刚" , "小丽" , "小华" } common_friends = xiaoming_friends & xiaohong_friends allowed_commands = {"start" , "stop" , "pause" } if command in allowed_commands: execute(command)
性能对比 不同操作的时间复杂度:
操作
列表
元组
字典
集合
访问元素
O(1)
O(1)
O(1)
-
查找元素
O(n)
O(n)
O(1)
O(1)
添加元素
O(1)*
-
O(1)
O(1)
删除元素
O(n)
-
O(1)
O(1)
遍历
O(n)
O(n)
O(n)
O(n)
*注:append() 是 O(1),insert(0) 是 O(n)
常见错误与最佳实践 常见错误 错误1:混淆列表和元组的可变性 ❌ 错误代码:
1 2 3 my_tuple = (1 , 2 , 3 ) my_tuple[0 ] = 100
✅ 正确理解:
1 2 3 4 5 6 7 8 9 my_list = [1 , 2 , 3 ] my_list[0 ] = 100 print (my_list) my_tuple = (1 , 2 , 3 ) my_tuple = (100 ,) + my_tuple[1 :] print (my_tuple)
错误2:空集合创建错误 ❌ 错误代码:
1 2 3 empty = {} print (type (empty))
✅ 正确代码:
1 2 3 4 5 6 7 empty_set = set () print (type (empty_set)) my_set = {1 , 2 , 3 } print (type (my_set))
错误3:直接赋值而非复制 ❌ 错误代码:
1 2 3 4 5 list1 = [1 , 2 , 3 ] list2 = list1 list2[0 ] = 100 print (list1)
✅ 正确代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 list1 = [1 , 2 , 3 ] list2 = list1.copy() list2 = list1[:] list2 = list (list1) list2[0 ] = 100 print (list1) print (list2)
错误4:在循环中修改列表 ❌ 错误代码:
1 2 3 4 5 6 7 8 numbers = [1 , 2 , 3 , 4 , 5 ] for num in numbers: if num % 2 == 0 : numbers.remove(num) print (numbers)
✅ 正确代码:
1 2 3 4 5 6 7 8 9 10 11 numbers = [1 , 2 , 3 , 4 , 5 ] odd_numbers = [num for num in numbers if num % 2 != 0 ] print (odd_numbers) numbers = [1 , 2 , 3 , 4 , 5 ] for i in range (len (numbers) - 1 , -1 , -1 ): if numbers[i] % 2 == 0 : numbers.pop(i) print (numbers)
错误5:字典键的类型错误 ❌ 错误代码:
1 2 3 4 my_dict = { [1 , 2 ]: "value" }
✅ 正确代码:
1 2 3 4 5 6 7 8 9 10 11 my_dict = { (1 , 2 ): "value" } my_dict = { "key" : "value" , 1 : "one" , (1 , 2 ): "tuple_key" }
错误6:集合包含可变类型 ❌ 错误代码:
1 2 my_set = {1 , 2 , [3 , 4 ]}
✅ 正确代码:
1 2 3 4 5 my_set = {1 , 2 , (3 , 4 )} my_set = {1 , 2 , frozenset ([3 , 4 ])}
编程技巧 技巧1:使用推导式简化代码 普通写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 squares = [] for i in range (10 ): squares.append(i ** 2 ) word_lengths = {} for word in words: word_lengths[word] = len (word) evens = set () for i in range (20 ): if i % 2 == 0 : evens.add(i)
推导式(推荐):
1 2 3 4 5 6 7 8 squares = [i ** 2 for i in range (10 )] word_lengths = {word: len (word) for word in words} evens = {i for i in range (20 ) if i % 2 == 0 }
技巧2:使用 get() 安全访问字典 不推荐:
1 2 3 4 if key in my_dict: value = my_dict[key] else : value = default_value
推荐:
1 2 3 4 5 value = my_dict.get(key, default_value) value = my_dict.setdefault(key, default_value)
技巧3:使用 enumerate() 获取索引 不推荐:
1 2 3 4 fruits = ["苹果" , "香蕉" , "橙子" ] for i in range (len (fruits)): print (f"{i} : {fruits[i]} " )
推荐:
1 2 3 4 5 6 7 8 fruits = ["苹果" , "香蕉" , "橙子" ] for i, fruit in enumerate (fruits): print (f"{i} : {fruit} " ) for i, fruit in enumerate (fruits, start=1 ): print (f"{i} : {fruit} " )
技巧4:使用 zip() 并行遍历 1 2 3 4 5 6 7 8 9 names = ["小明" , "小红" , "小刚" ] scores = [85 , 92 , 78 ] for name, score in zip (names, scores): print (f"{name} : {score} 分" ) student_scores = dict (zip (names, scores))
技巧5:使用 * 解包 1 2 3 4 5 6 7 8 9 10 11 12 13 numbers = [1 , 2 , 3 , 4 , 5 ] first, *middle, last = numbers print (f"第一个:{first} " ) print (f"中间:{middle} " ) print (f"最后一个:{last} " ) def add (a, b, c ): return a + b + c nums = [1 , 2 , 3 ] result = add(*nums)
技巧6:使用集合提高查找效率 不推荐(列表查找慢):
1 2 3 4 valid_users = ["user1" , "user2" , "user3" , ...] if username in valid_users: login()
推荐(集合查找快):
1 2 3 4 valid_users = {"user1" , "user2" , "user3" , ...} if username in valid_users: login()
综合案例:学生管理系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 class StudentManager : def __init__ (self ): self.students = {} self.student_ids = set () self.classes = {} self.subjects = ("语文" , "数学" , "英语" ) def add_student (self, student_id, name, class_name, scores ): """添加学生""" if student_id in self.student_ids: print (f"❌ 学号 {student_id} 已存在" ) return False self.students[student_id] = { "name" : name, "class" : class_name, "scores" : scores } self.student_ids.add(student_id) if class_name not in self.classes: self.classes[class_name] = [] self.classes[class_name].append(student_id) print (f"✅ 成功添加学生:{name} " ) return True def get_student (self, student_id ): """查询学生信息""" if student_id not in self.student_ids: print (f"❌ 学号 {student_id} 不存在" ) return None student = self.students[student_id] print (f"\n学号:{student_id} " ) print (f"姓名:{student['name' ]} " ) print (f"班级:{student['class' ]} " ) for subject, score in zip (self.subjects, student['scores' ]): print (f"{subject} :{score} 分" ) return student def get_class_average (self, class_name ): """计算班级平均分""" if class_name not in self.classes: print (f"❌ 班级 {class_name} 不存在" ) return None student_ids = self.classes[class_name] if not student_ids: print (f"❌ 班级 {class_name} 没有学生" ) return None all_scores = [ score for sid in student_ids for score in self.students[sid]['scores' ] ] average = sum (all_scores) / len (all_scores) print (f"\n{class_name} 班级平均分:{average:.2 f} " ) return average def find_top_students (self, n=3 ): """找出前N名学生""" student_averages = [] for sid, info in self.students.items(): avg = sum (info['scores' ]) / len (info['scores' ]) student_averages.append((sid, info['name' ], avg)) student_averages.sort(key=lambda x: x[2 ], reverse=True ) top_n = student_averages[:n] print (f"\n前 {n} 名学生:" ) for i, (sid, name, avg) in enumerate (top_n, 1 ): print (f"{i} . {name} ({sid} )- 平均分:{avg:.2 f} " ) return top_n def get_subject_stats (self, subject_index ): """统计某科目的成绩""" if subject_index >= len (self.subjects): print ("❌ 科目索引无效" ) return None subject = self.subjects[subject_index] scores = [ student['scores' ][subject_index] for student in self.students.values() ] if not scores: print (f"❌ 没有 {subject} 成绩" ) return None print (f"\n{subject} 成绩统计:" ) print (f"最高分:{max (scores)} " ) print (f"最低分:{min (scores)} " ) print (f"平均分:{sum (scores) / len (scores):.2 f} " ) unique_scores = set (scores) print (f"不同分数数量:{len (unique_scores)} " ) return scores def main (): manager = StudentManager() print ("=== 添加学生 ===" ) manager.add_student("S001" , "小明" , "一班" , [85 , 90 , 88 ]) manager.add_student("S002" , "小红" , "一班" , [92 , 95 , 90 ]) manager.add_student("S003" , "小刚" , "二班" , [78 , 82 , 80 ]) manager.add_student("S004" , "小丽" , "一班" , [95 , 92 , 96 ]) manager.add_student("S005" , "小华" , "二班" , [88 , 86 , 90 ]) print ("\n=== 查询学生 ===" ) manager.get_student("S002" ) print ("\n=== 班级平均分 ===" ) manager.get_class_average("一班" ) manager.get_class_average("二班" ) print ("\n=== 排行榜 ===" ) manager.find_top_students(3 ) print ("\n=== 数学成绩统计 ===" ) manager.get_subject_stats(1 ) print ("\n" + "=" * 50 ) if __name__ == "__main__" : main()
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 === 添加学生 === ✅ 成功添加学生:小明 ✅ 成功添加学生:小红 ✅ 成功添加学生:小刚 ✅ 成功添加学生:小丽 ✅ 成功添加学生:小华 === 查询学生 === 学号:S002 姓名:小红 班级:一班 语文:92分 数学:95分 英语:90分 === 班级平均分 === 一班 班级平均分:90.44 二班 班级平均分:84.00 === 排行榜 === 前 3 名学生: 1. 小丽(S004)- 平均分:94.33 2. 小红(S002)- 平均分:92.33 3. 小华(S005)- 平均分:88.00 === 数学成绩统计 === 数学 成绩统计: 最高分:95 最低分:82 平均分:89.00 不同分数数量:5 ==================================================
总结 知识点回顾 1️⃣ 列表 (list)
特点 :有序、可变、可重复
创建 :[] 或 list()
适用 :需要修改的有序数据
方法 :append、insert、remove、pop、sort、reverse
2️⃣ 元组 (tuple)
特点 :有序、不可变、可重复
创建 :() 或 tuple()
适用 :不需修改的数据、函数返回多值
特性 :元组解包、可作为字典的键
3️⃣ 字典 (dict)
特点 :键值对、无序*、键唯一、快速查找
创建 :{} 或 dict()
适用 :需要通过键访问值
方法 :get、keys、values、items、update、pop
4️⃣ 集合 (set)
特点 :无序、唯一、快速查找
创建 :{} 或 set()
适用 :去重、集合运算、快速查找
运算 :并集 |、交集 &、差集 -、对称差集 ^
重要提醒
⚠️ 空集合 要用 set(),不能用 {}(那是空字典)
⚠️ 直接赋值 不会复制数据结构,而是创建引用
⚠️ 元组不可变 ,但可以包含可变对象(如列表)
⚠️ 字典的键 和集合的元素 必须是可哈希的(不可变)
⚠️ 在循环中修改列表 可能导致跳过元素
⚠️ 推导式 是创建数据结构的简洁方式
学习建议
理解特点 :掌握每种数据结构的特点和适用场景
多练习 :通过实际编码加深理解
性能意识 :了解不同操作的时间复杂度
灵活运用 :根据需求选择合适的数据结构
推导式 :熟练使用推导式简化代码
组合使用 :实际项目中常常需要组合使用多种数据结构
数据结构应用场景总结
场景
推荐数据结构
原因
存储有序数据
列表/元组
支持索引访问
频繁修改数据
列表
可变
保护数据不被修改
元组
不可变
键值映射
字典
通过键快速访问值
去除重复
集合
自动去重
快速查找
字典/集合
O(1) 时间复杂度
集合运算
集合
支持交并差运算
函数返回多值
元组
不可变、安全
配置信息
字典/元组
键值对或不可变
计数统计
字典
键值对映射
Q&A
A:
列表(可变) :可以修改、添加、删除元素
元组(不可变) :创建后不能修改
选择标准:
数据会改变 → 用列表
数据不会改变 → 用元组(更安全、更快)
作为字典的键 → 必须用元组(列表不可哈希)
A: 因为字典在 Python 中出现得更早,{} 被用来表示空字典。
记住:
空字典:{}
空集合:set()
非空集合:{1, 2, 3}
A:
字典 :存储键值对,通过键访问值
集合 :只存储元素(相当于只有键没有值)
相同点:
都使用 {} 创建
都是无序的
查找速度都很快(O(1))
键/元素都必须是可哈希的
选择:
需要键值映射 → 用字典
只需要去重或集合运算 → 用集合
A: 可哈希是指对象的值在生命周期内不会改变。
可哈希的类型(可以作为字典的键或集合的元素):
✅ 数字:int、float
✅ 字符串:str
✅ 元组:tuple
✅ 布尔值:bool
✅ None
不可哈希的类型(不能作为字典的键或集合的元素):
❌ 列表:list
❌ 字典:dict
❌ 集合:set
A: 问自己这些问题:
需要顺序吗?
会修改吗?
需要键值对吗?
允许重复吗?
A:
直接赋值 :创建引用,两个变量指向同一个对象
复制 :创建新对象,两个变量独立
1 2 3 4 5 6 7 8 9 10 11 list1 = [1 , 2 , 3 ] list2 = list1 list2[0 ] = 100 print (list1) list1 = [1 , 2 , 3 ] list2 = list1.copy() list2[0 ] = 100 print (list1)
A: 当你需要基于现有序列创建新序列时:
1 2 3 4 5 6 7 8 9 10 squares = [] for i in range (10 ): squares.append(i ** 2 ) squares = [i ** 2 for i in range (10 )] evens = [i for i in range (20 ) if i % 2 == 0 ]
建议:
简单的转换 → 用推导式
复杂的逻辑 → 用传统循环(更清晰)
🎉 恭喜你完成了 Python 数据结构的学习!
数据结构是编程的基础,掌握好这四种数据结构,你就能高效地组织和管理数据。
现在你已经学会了:
✅ 列表 :存储和操作有序数据
✅ 元组 :保护数据不被修改
✅ 字典 :键值映射和快速查找
✅ 集合 :去重和集合运算
接下来可以学习函数 ,让代码更加模块化和可重用!
记住 :选择合适的数据结构能让你的代码更高效、更优雅!💪