Python教程16:数据结构综合实战

Python 教程 16:数据结构综合实战 “纸上得来终觉浅,绝知此事要躬行。” 学习了列表、元组、字典、集合后,让我们通过一个实际项目——学生成绩管理系统,把这些知识串起来,体会如何选择和组合不同的数据结构。 1. 项目需求 开发一个学生成绩管理系统,功能包括: 添加学生信息 录入和修改成绩 查询学生成绩 统计分析(平均分、最高分等) 筛选功能(如成绩优秀的学生) 2. 数据结构设计 方案选择 1# 学生信息:用字典 2student = { 3 "id": "2024001", 4 "name": "张三", 5 "age": 18, 6 "scores": { # 成绩:嵌套字典 7 "数学": 95, 8 "英语": 88, 9 "物理": 92 10 } 11} 12 13# 所有学生:用列表存储 14students = [ 15 {"id": "2024001", "name": "张三", "age": 18, "scores": {"数学": 95}}, 16 {"id": "2024002", "name": "李四", "age": 19, "scores": {"数学": 88}}, 17] 18 19# 学号索引:用字典加速查找 20students_by_id = { 21 "2024001": students[0], 22 "2024002": students[1], 23} 3. 核心功能实现 3.1 学生管理类 1class StudentManager: 2 """学生成绩管理系统""" 3 4 def __init__(self): 5 self.students = {} # {学号: 学生信息} 6 7 def add_student(self, student_id, name, age): 8 """添加学生""" 9 if student_id in self.students: 10 print(f"学号{student_id}已存在") 11 return False 12 13 self.students[student_id] = { 14 "id": student_id, 15 "name": name, 16 "age": age, 17 "scores": {} 18 } 19 print(f"✓ 添加学生:{name}") 20 return True 21 22 def add_score(self, student_id, subject, score): 23 """添加成绩""" 24 if student_id not in self.students: 25 print(f"学号{student_id}不存在") 26 return False 27 28 self.students[student_id]["scores"][subject] = score 29 print(f"✓ 录入成绩:{subject} = {score}") 30 return True 31 32 def get_student(self, student_id): 33 """查询学生信息""" 34 return self.students.get(student_id) 35 36 def get_average(self, student_id): 37 """计算学生平均分""" 38 student = self.get_student(student_id) 39 if not student or not student["scores"]: 40 return None 41 42 scores = student["scores"].values() 43 return sum(scores) / len(scores) 44 45 def get_top_students(self, n=5): 46 """获取成绩最好的N名学生""" 47 # 计算每个学生的平均分 48 student_avgs = [] 49 for sid, student in self.students.items(): 50 if student["scores"]: 51 avg = sum(student["scores"].values()) / len(student["scores"]) 52 student_avgs.append((student["name"], avg)) 53 54 # 排序并返回前N名 55 student_avgs.sort(key=lambda x: x[1], reverse=True) 56 return student_avgs[:n] 57 58 def get_subject_stats(self, subject): 59 """统计某科目的成绩分布""" 60 scores = [] 61 for student in self.students.values(): 62 if subject in student["scores"]: 63 scores.append(student["scores"][subject]) 64 65 if not scores: 66 return None 67 68 return { 69 "count": len(scores), 70 "max": max(scores), 71 "min": min(scores), 72 "avg": sum(scores) / len(scores) 73 } 74 75 def find_by_score_range(self, subject, min_score, max_score): 76 """查找某科目分数在指定范围内的学生""" 77 result = [] 78 for student in self.students.values(): 79 if subject in student["scores"]: 80 score = student["scores"][subject] 81 if min_score <= score <= max_score: 82 result.append({ 83 "name": student["name"], 84 "score": score 85 }) 86 return result 3.2 使用示例 1# 创建管理器 2manager = StudentManager() 3 4# 添加学生 5manager.add_student("2024001", "张三", 18) 6manager.add_student("2024002", "李四", 19) 7manager.add_student("2024003", "王五", 18) 8 9# 录入成绩 10manager.add_score("2024001", "数学", 95) 11manager.add_score("2024001", "英语", 88) 12manager.add_score("2024001", "物理", 92) 13 14manager.add_score("2024002", "数学", 87) 15manager.add_score("2024002", "英语", 94) 16manager.add_score("2024002", "物理", 89) 17 18manager.add_score("2024003", "数学", 92) 19manager.add_score("2024003", "英语", 85) 20manager.add_score("2024003", "物理", 95) 21 22# 查询学生 23student = manager.get_student("2024001") 24print(f"\n学生信息:{student['name']}") 25print(f"成绩:{student['scores']}") 26 27# 计算平均分 28avg = manager.get_average("2024001") 29print(f"平均分:{avg:.2f}") 30 31# 获取前3名 32print("\n前3名学生:") 33top_students = manager.get_top_students(3) 34for i, (name, avg) in enumerate(top_students, 1): 35 print(f"{i}. {name}: {avg:.2f}") 36 37# 统计数学成绩 38print("\n数学成绩统计:") 39stats = manager.get_subject_stats("数学") 40print(f"人数:{stats['count']}") 41print(f"最高分:{stats['max']}") 42print(f"最低分:{stats['min']}") 43print(f"平均分:{stats['avg']:.2f}") 44 45# 查找数学成绩90分以上的学生 46print("\n数学90分以上:") 47excellent = manager.find_by_score_range("数学", 90, 100) 48for item in excellent: 49 print(f"{item['name']}: {item['score']}") 4. 数据结构选择分析 为什么用字典存储学生 1# 方案1:列表(不推荐) 2students_list = [...] 3# 查找学生需要遍历:O(n) 4 5# 方案2:字典(推荐) 6students_dict = {"2024001": {...}} 7# 查找学生直接访问:O(1) 选择依据:需要频繁通过学号查找学生,字典更高效。 ...

2024-07-01 · 3 min · 633 words · 老墨

Python教程15:集合

Python 教程 15:集合 “世界上没有两片完全相同的树叶。” 集合(Set)是 Python 中一个特殊的数据结构,它最大的特点是元素唯一、无序。就像数学中的集合概念,非常适合去重和集合运算。 1. 什么是集合 集合是一个无序的、不重复的元素集合。 1# 创建集合 2empty_set = set() # 空集合(注意不是{}) 3numbers = {1, 2, 3, 4, 5} 4mixed = {1, "hello", 3.14, True} 5 6# 使用set()函数 7from_list = set([1, 2, 2, 3, 3, 3]) # {1, 2, 3}(自动去重) 8from_string = set("hello") # {'h', 'e', 'l', 'o'} 9 10# 集合推导式 11squares = {x**2 for x in range(5)} # {0, 1, 4, 9, 16} 注意:{}是空字典,不是空集合! 1empty_dict = {} 2empty_set = set() 3 4print(type(empty_dict)) # <class 'dict'> 5print(type(empty_set)) # <class 'set'> 2. 集合的基本操作 1fruits = {"苹果", "香蕉", "橙子"} 2 3# 添加元素 4fruits.add("葡萄") 5print(fruits) # {'苹果', '香蕉', '橙子', '葡萄'} 6 7# 添加多个元素 8fruits.update(["西瓜", "芒果"]) 9print(fruits) 10 11# 删除元素 12fruits.remove("香蕉") # 不存在会报错 13# fruits.remove("榴莲") # KeyError 14 15fruits.discard("橙子") # 不存在不报错 16fruits.discard("榴莲") # 不会报错 17 18# pop():randomly删除并返回一个元素 19item = fruits.pop() 20print(f"删除了:{item}") 21 22# clear():清空 23fruits.clear() 3. 集合运算 集合支持数学中的集合运算: ...

2024-06-04 · 3 min · 542 words · 老墨

Python教程14:字典基础

Python 教程 14:字典基础 “一把钥匙开一把锁。” 字典(Dictionary)是 Python 中最灵活、最强大的数据结构之一。它通过"键-值对"的方式存储数据,就像真实世界的字典用单词查释义一样。 1. 什么是字典 字典是一个无序的、可变的键值对集合。 1# 创建字典 2empty_dict = {} # 空字典 3user = { 4 "name": "张三", 5 "age": 25, 6 "city": "北京" 7} 8 9# 使用dict()函数 10from_pairs = dict([("a", 1), ("b", 2)]) 11from_keywords = dict(name="李四", age=30) 12 13# 字典推导式 14squares = {x: x**2 for x in range(5)} 15# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 2. 访问字典 1user = {"name": "张三", "age": 25, "city": "北京"} 2 3# 方法1:[]访问 4print(user["name"]) # 张三 5# print(user["phone"]) # KeyError: 键不存在会报错 6 7# 方法2:get()方法(推荐) 8print(user.get("name")) # 张三 9print(user.get("phone")) # None(不报错) 10print(user.get("phone", "未设置")) # 未设置(默认值) 11 12# 检查键是否存在 13print("name" in user) # True 14print("phone" in user) # False 15print("phone" not in user) # True 3. 修改字典 1user = {"name": "张三", "age": 25} 2 3# 修改值 4user["age"] = 26 5print(user) # {'name': '张三', 'age': 26} 6 7# 添加键值对 8user["city"] = "上海" 9print(user) # {'name': '张三', 'age': 26, 'city': '上海'} 10 11# 删除键值对 12del user["city"] 13print(user) # {'name': '张三', 'age': 26} 14 15# pop():删除并返回值 16age = user.pop("age") 17print(age) # 26 18print(user) # {'name': '张三'} 19 20# popitem():删除并返回最后一个键值对(3.7+有序) 21user = {"a": 1, "b": 2, "c": 3} 22item = user.popitem() 23print(item) # ('c', 3) 4. 字典常用方法 获取键、值、项 1user = {"name": "张三", "age": 25, "city": "北京"} 2 3# keys():所有键 4print(user.keys()) # dict_keys(['name', 'age', 'city']) 5print(list(user.keys())) # ['name', 'age', 'city'] 6 7# values():所有值 8print(user.values()) # dict_values(['张三', 25, '北京']) 9print(list(user.values())) # ['张三', 25, '北京'] 10 11# items():所有键值对 12print(user.items()) 13# dict_items([('name', '张三'), ('age', 25), ('city', '北京')]) 14 15# 转换为列表 16items_list = list(user.items()) 17print(items_list) 18# [('name', '张三'), ('age', 25), ('city', '北京')] 更新和清空 1user = {"name": "张三", "age": 25} 2 3# update():更新字典 4user.update({"age": 26, "city": "北京"}) 5print(user) 6# {'name': '张三', 'age': 26, 'city': '北京'} 7 8# 也可以用关键字参数 9user.update(phone="13800138000") 10print(user) 11 12# clear():清空字典 13user.clear() 14print(user) # {} setdefault() 如果键存在,返回其值;否则设置默认值并返回: ...

2024-06-03 · 3 min · 607 words · 老墨

Python教程13:元组

Python 教程 13:元组 “不变,有时候是一种力量。” 元组和列表很像,但有一个关键区别:元组是不可变的。这个特性让元组在某些场景下比列表更安全、更高效。 1. 什么是元组 元组(Tuple)是一个有序的、不可变的元素集合。 1# 创建元组 2empty_tuple = () # 空元组 3single = (1,) # 单元素元组(注意逗号) 4numbers = (1, 2, 3, 4, 5) 5mixed = (1, "hello", 3.14, True) 6nested = ((1, 2), (3, 4)) 7 8# 也可以不用括号(但不推荐) 9point = 10, 20 10print(point) # (10, 20) 11 12# 使用tuple()函数 13from_list = tuple([1, 2, 3]) 14from_string = tuple("Python") # ('P', 'y', 't', 'h', 'o', 'n') 注意:单元素元组必须有逗号! 1not_a_tuple = (1) # 这是整数1 2is_a_tuple = (1,) # 这才是元组 2. 访问元组元素 元组的访问方式和列表完全相同: 1fruits = ("苹果", "香蕉", "橙子", "葡萄") 2 3# 索引 4print(fruits[0]) # 苹果 5print(fruits[-1]) # 葡萄 6 7# 切片 8print(fruits[1:3]) # ('香蕉', '橙子') 9print(fruits[::-1]) # ('葡萄', '橙子', '香蕉', '苹果') 10 11# 遍历 12for fruit in fruits: 13 print(fruit) 14 15# enumerate 16for i, fruit in enumerate(fruits): 17 print(f"{i}: {fruit}") 3. 元组的不可变性 元组创建后不能修改: ...

2024-05-21 · 3 min · 547 words · 老墨

Python教程12:列表进阶与推导式高级

Python教程12:列表进阶与推导式高级 “熟能生巧,巧能生精。” 在第8课我们学习了列表推导式的基础,今天我们深入探讨列表推导式的高级技巧和列表的进阶操作,让你的代码更加Pythonic和高效。 1. 回顾:列表推导式基础 1# 基础语法 2squares = [x**2 for x in range(10)] 3 4# 带条件 5evens = [x for x in range(10) if x % 2 == 0] 6 7# if-else 8result = [x if x > 0 else 0 for x in [-1, 2, -3, 4]] 2. 嵌套列表推导式 二维列表展平 1# 传统方法 2matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 3flat = [] 4for row in matrix: 5 for num in row: 6 flat.append(num) 7 8# 列表推导式 9flat = [num for row in matrix for num in row] 10print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9] 理解技巧:从左到右阅读,就像嵌套的for循环。 创建二维列表 1# 创建3×3矩阵 2matrix = [[0 for _ in range(3)] for _ in range(3)] 3print(matrix) 4# [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 5 6# 创建乘法表 7table = [[i*j for j in range(1, 10)] for i in range(1, 10)] 8 9# 注意:不要这样创建二维列表 10# bad = [[0] * 3] * 3 # 错误!所有行是同一个对象 多重嵌套with条件 1# 找出两个列表的所有组合(有条件) 2a = [1, 2, 3] 3b = [3, 4, 5] 4 5# 找出和大于5的组合 6result = [(x, y) for x in a for y in b if x + y > 5] 7print(result) # [(2, 4), (2, 5), (3, 3), (3, 4), (3, 5)] 3. 列表推导式vs传统循环 1# 性能对比示例 2import time 3 4# 方法1:传统for循环 5start = time.time() 6result1 = [] 7for i in range(100000): 8 result1.append(i**2) 9time1 = time.time() - start 10 11# 方法2:列表推导式 12start = time.time() 13result2 = [i**2 for i in range(100000)] 14time2 = time.time() - start 15 16print(f"传统循环:{time1:.4f}秒") 17print(f"列表推导式:{time2:.4f}秒") 18# 列表推导式通常快20-30% 4. 字典和集合推导式进阶 字典推导式高级用法 1# 统计字符出现次数 2text = "hello world" 3char_count = {char: text.count(char) for char in set(text) if char != ' '} 4 5# 从列表创建索引字典 6fruits = ['apple', 'banana', 'cherry'] 7fruit_index = {fruit: i for i, fruit in enumerate(fruits)} 8 9# 嵌套字典推导式 10students = ['Alice', 'Bob'] 11subjects = ['Math', 'English'] 12grades = { 13 student: {subject: 0 for subject in subjects} 14 for student in students 15} 集合推导式妙用 1# 去重并转换 2numbers = [1, -2, 3, -4, 5] 3abs_unique = {abs(n) for n in numbers} # {1, 2, 3, 4, 5} 4 5# 找差异 6list1 = [1, 2, 3, 4, 5] 7list2 = [4, 5, 6, 7, 8] 8diff = {x for x in list1 if x not in list2} # {1, 2, 3} 5. 生成器表达式深入 1# 列表推导式:立即生成,占内存 2squares_list = [x**2 for x in range(1000000)] 3 4# 生成器表达式:按需生成,省内存 5squares_gen = (x**2 for x in range(1000000)) 6 7# 使用生成器 8total = sum(x**2 for x in range(1000000)) 9 10# 生成器只能遍历一次 11gen = (x for x in range(5)) 12print(list(gen)) # [0, 1, 2, 3, 4] 13print(list(gen)) # [](已耗尽) 6. 列表的高级操作 zip和enumerate进阶 1# zip并行遍历 2names = ['Alice', 'Bob', 'Charlie'] 3ages = [25, 30, 35] 4cities = ['Beijing', 'Shanghai', 'Guangzhou'] 5 6# 创建字典 7people = [ 8 {'name': n, 'age': a, 'city': c} 9 for n, a, c in zip(names, ages, cities) 10] 11 12# enumerate with start 13for i, name in enumerate(names, start=1): 14 print(f"{i}. {name}") filter和map结合推导式 1# 虽然有filter和map,但推导式更清晰 2numbers = range(1, 11) 3 4# filter + map方式 5result1 = list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, numbers))) 6 7# 推导式方式(更清晰) 8result2 = [x**2 for x in numbers if x % 2 == 0] 7. 实战案例 案例1:矩阵转置 1matrix = [ 2 [1, 2, 3], 3 [4, 5, 6], 4 [7, 8, 9] 5] 6 7# 转置 8transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))] 9print(transposed) 10# [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 11 12# 或使用zip 13transposed = [list(col) for col in zip(*matrix)] 案例2:笛卡尔积 1colors = ['红', '黑'] 2sizes = ['S', 'M', 'L'] 3products = [f"{color}-{size}" for color in colors for size in sizes] 4# ['红-S', '红-M', '红-L', '黑-S', '黑-M', '黑-L'] 案例3:数据清洗 1# 清洗CSV数据 2raw_data = [ 3 " Alice, 25 ", 4 "Bob,30", 5 " Charlie, 35 " 6] 7 8cleaned = [ 9 [item.strip() for item in row.split(',')] 10 for row in raw_data 11] 8. 何时不用推导式 虽然推导式简洁,但有时不适合: ...

2024-04-28 · 4 min · 744 words · 老墨

Python教程11:列表基础

Python教程11:列表基础 “工欲善其事,必先利其器。” 列表(List)是Python中最常用的数据结构之一,就像一个可以随意增删改查的购物清单。今天我们深入学习列表的基础操作,为后续学习打好基础。 1. 什么是列表 列表是一个有序的、可变的元素集合,可以存储不同类型的数据。 1# 创建列表 2empty_list = [] # 空列表 3numbers = [1, 2, 3, 4, 5] # 整数列表 4mixed = [1, "hello", 3.14, True] # 混合类型 5nested = [[1, 2], [3, 4], [5, 6]] # 嵌套列表 6 7# 使用list()函数 8from_string = list("Python") # ['P', 'y', 't', 'h', 'o', 'n'] 9from_range = list(range(5)) # [0, 1, 2, 3, 4] 2. 访问列表元素 索引访问 1fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"] 2 3# 正向索引(从0开始) 4print(fruits[0]) # 苹果 5print(fruits[1]) # 香蕉 6 7# 负向索引(从-1开始) 8print(fruits[-1]) # 西瓜(最后一个) 9print(fruits[-2]) # 葡萄(倒数第二个) 10 11# 索引越界会报错 12# print(fruits[10]) # IndexError 切片访问 1numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 3# [start:stop:step] 4print(numbers[2:5]) # [2, 3, 4] 5print(numbers[:5]) # [0, 1, 2, 3, 4] 6print(numbers[5:]) # [5, 6, 7, 8, 9] 7print(numbers[::2]) # [0, 2, 4, 6, 8](步长为2) 8print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0](反转) 9 10# 负索引切片 11print(numbers[-3:]) # [7, 8, 9] 12print(numbers[:-3]) # [0, 1, 2, 3, 4, 5, 6] 3. 修改列表 列表是可变的,可以直接修改元素: ...

2024-04-15 · 4 min · 750 words · 老墨