04 数据结构
📋 资料说明
- 来源:课程 day03~day04
- 笔记:
尚硅谷大模型技术之Python1.0.docx第 5 章"数据结构" - 每日一考:
day03_每日一考.md、day04_每日一考.md - 视频:❌ 跳过(约 24 个视频:列表 → 字符串 → 元组 → 集合 → 字典)
🟢 🤖 AI 替代率:98%
为什么是这个水平:
Python 内建数据结构的 API(增删改查方法)是确定性知识。AI 对 list.append()、dict.get()、set.union() 等方法的参数、返回值和副作用的描述准确率极高。唯一的 2% 不确定性在于:深拷贝/浅拷贝涉及的内存模型理解——但这一对比差异已在函数章节中讨论。
👤 人工干预率:2%
极低。建议了解不同数据结构的选型原则(什么场景用列表、什么场景用字典、什么时候用集合),这在实际项目中比记住所有 API 更重要。AI 可以帮你写代码,但你要告诉 AI 用什么数据结构。
1. 列表 (list)
Python 列表是可变、有序、可重复的序列。
创建与访问
python
# 创建
empty = []
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
nested = [[1, 2], [3, 4]] # 嵌套列表
# 索引(从 0 开始)
print(numbers[0]) # 1
print(numbers[-1]) # 5 (负数索引从右开始)
print(numbers[-2]) # 4
# 切片 [start:stop:step]
print(numbers[1:3]) # [2, 3]
print(numbers[:3]) # [1, 2, 3]
print(numbers[::2]) # [1, 3, 5]
print(numbers[::-1]) # [5, 4, 3, 2, 1](反转)常用操作
python
fruits = ["苹果", "香蕉"]
# 增
fruits.append("橘子") # 末尾添加
fruits.insert(1, "葡萄") # 指定位置插入
fruits.extend(["西瓜", "芒果"]) # 合并列表
# 删
fruits.remove("香蕉") # 删除指定元素(第一个匹配项)
popped = fruits.pop() # 删除并返回最后一个
popped = fruits.pop(1) # 删除并返回索引为 1 的元素
fruits.clear() # 清空所有元素
# 改
fruits[0] = "草莓" # 修改指定位置元素
# 查
print("苹果" in fruits) # True(成员判断)
print(fruits.index("香蕉")) # 查找索引(不存在抛出 ValueError)
print(fruits.count("苹果")) # 统计出现次数列表排序
python
numbers = [3, 1, 4, 1, 5, 9, 2]
# 原地排序(修改原列表)
numbers.sort() # [1, 1, 2, 3, 4, 5, 9]
numbers.sort(reverse=True) # [9, 5, 4, 3, 2, 1, 1]
# 返回新列表
sorted_numbers = sorted(numbers)
# 自定义排序
words = ["banana", "apple", "cherry"]
words.sort(key=len) # 按字符串长度排序列表推导式
python
# [表达式 for 变量 in 可迭代对象 if 条件]
# 基本
squares = [x**2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件
evens = [x for x in range(20) if x % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 嵌套循环
pairs = [(x, y) for x in [1, 2] for y in [3, 4]]
# [(1, 3), (1, 4), (2, 3), (2, 4)]
# 条件表达式
labels = ["偶数" if x % 2 == 0 else "奇数" for x in range(5)]
# ['偶数', '奇数', '偶数', '奇数', '偶数']常用函数
python
numbers = [3, 1, 4, 1, 5]
print(len(numbers)) # 5(长度)
print(sum(numbers)) # 14(总和)
print(max(numbers)) # 5(最大值)
print(min(numbers)) # 1(最小值)2. 字符串 (str)
字符串是不可变序列。
常用操作
python
s = "Hello, Python World"
# 大小写
print(s.upper()) # HELLO, PYTHON WORLD
print(s.lower()) # hello, python world
print(s.capitalize()) # Hello, python world
print(s.title()) # Hello, Python World
# 查找
print(s.find("Python")) # 7(索引位置,-1 表示未找到)
print(s.index("Python")) # 7(不存在抛出 ValueError)
print(s.count("o")) # 3(出现次数)
print(s.startswith("Hello")) # True
print(s.endswith("World")) # True
# 替换
print(s.replace("Python", "Java")) # Hello, Java World
# 分割与连接
words = s.split() # ['Hello,', 'Python', 'World']
print(words)
print(", ".join(words)) # Hello,, Python, World
# 去除空白
s2 = " hello "
print(s2.strip()) # "hello"
print(s2.lstrip()) # "hello "
print(s2.rstrip()) # " hello"
# 判断
print("123".isdigit()) # True
print("abc".isalpha()) # True
print("abc123".isalnum()) # True
# 字符串格式化(详见 02 章)
name = "Alice"
age = 25
print(f"{name} is {age} years old")注意事项: 字符串是不可变对象,所有"修改"操作都返回新字符串,原字符串不变。
3. 元组 (tuple)
元组是不可变、有序、可重复的序列。
python
# 创建
empty = ()
single = (1,) # 注意逗号,不加逗号是整数
numbers = (1, 2, 3, 4, 5)
mixed = (1, "hello", 3.14)
# 访问(与列表相同)
print(numbers[0]) # 1
print(numbers[1:3]) # (2, 3)
# 元组是不可变的,不能修改元素
# numbers[0] = 10 # ❌ TypeError
# 元组解包
a, b, c = (1, 2, 3)
print(a, b, c) # 1 2 3
# 交换变量(本质是元组解包)
x, y = 10, 20
x, y = y, x
print(x, y) # 20 10什么时候用元组?
- 数据不应被修改(如坐标、数据库记录)
- 作为字典的键(列表不能做键)
- 函数返回多个值(实际上返回的就是元组)
4. 集合 (set)
集合是可变、无序、不重复的元素集合。
python
# 创建
empty = set() # 注意:{} 是空字典
numbers = {1, 2, 3, 3, 2, 1} # {1, 2, 3}(自动去重)
from_list = set([1, 2, 3, 3]) # {1, 2, 3}
# 增
numbers.add(4)
numbers.update([5, 6, 7]) # 批量添加
# 删
numbers.remove(3) # 删除指定元素(不存在抛出 KeyError)
numbers.discard(3) # 删除指定元素(不存在不报错)
numbers.pop() # 随机删除并返回一个元素
numbers.clear() # 清空
# 集合运算
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b) # 并集: {1, 2, 3, 4, 5, 6}
print(a & b) # 交集: {3, 4}
print(a - b) # 差集: {1, 2}
print(a ^ b) # 对称差: {1, 2, 5, 6}
# 判断
print(1 in a) # True
print(a.issubset(b)) # False(a 是否是 b 的子集)什么时候用集合?
- 去重
- 快速成员检查(
in操作时间复杂度 O(1),列表是 O(n))- 数学集合运算
5. 字典 (dict)
字典是键值对的无序集合(Python 3.7+ 保持插入顺序)。
python
# 创建
empty = {}
student = {
"name": "Alice",
"age": 25,
"scores": [90, 85, 92]
}
# 访问
print(student["name"]) # Alice(键不存在抛出 KeyError)
print(student.get("name")) # Alice(键不存在返回 None)
print(student.get("gender", "未知")) # "未知"(指定默认值)
# 增/改
student["gender"] = "女" # 键不存在则新增
student["age"] = 26 # 键存在则修改
student.update({"phone": "123", "email": "a@b.com"}) # 批量更新
# 删
del student["phone"] # 删除指定键
age = student.pop("age") # 删除并返回对应值
student.clear() # 清空
# 遍历
for key in student:
print(key, student[key])
for key, value in student.items():
print(key, value)
for key in student.keys():
print(key)
for value in student.values():
print(value)
# 字典推导式
squares = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 4}键的要求:键必须是不可变类型(字符串、数字、元组)。列表和字典不能做键。
defaultdict 和 Counter
python
from collections import defaultdict, Counter
# defaultdict:键不存在时自动创建默认值
word_count = defaultdict(int)
for word in ["a", "b", "a", "c", "b", "a"]:
word_count[word] += 1
print(dict(word_count)) # {'a': 3, 'b': 2, 'c': 1}
# Counter:计数更简单
counter = Counter(["a", "b", "a", "c", "b", "a"])
print(counter) # Counter({'a': 3, 'b': 2, 'c': 1})
print(counter.most_common(2)) # [('a', 3), ('b', 2)]数据结构选型指南
| 场景 | 推荐结构 | 原因 |
|---|---|---|
| 有序存储、可重复 | 列表 | 最通用的序列 |
| 需要快速去重 | 集合 | O(1) 查找 |
| 键值对映射 | 字典 | 通过键快速取值 |
| 只读数据、可哈希 | 元组 | 不可变、可作字典键 |
| 文本处理 | 字符串 | 丰富的 API |
6. 练习题
练习 1:列表操作
现有列表 my_list = [10, 20, 30, 40, 50]:
- 向末尾添加 60
- 取出索引为 2 的元素
- 计算所有元素的和
练习 2:字典操作
既有学生成绩字典:
python
students = {
"Alice": {"Math": 85, "English": 90, "Science": 78},
"Bob": {"Math": 92, "English": 88, "Science": 95},
"Charlie": {"Math": 70, "English": 75, "Science": 80}
}计算每个学生的平均分。
练习 3:去重
给定 [1, 2, 2, 3, 4, 3, 5],去重后排序输出。
练习 4:列表推导式
使用推导式生成 1~100 中所有能被 3 或 5 整除的数字。
参考答案
练习 1:
python
my_list = [10, 20, 30, 40, 50]
my_list.append(60)
element = my_list[2]
total = sum(my_list)
print(element, total) # 30 210练习 2:
python
for name, scores in students.items():
avg = sum(scores.values()) / len(scores)
print(f"{name}: {avg:.1f}")
# Alice: 84.3, Bob: 91.7, Charlie: 75.0练习 3:
python
nums = [1, 2, 2, 3, 4, 3, 5]
print(sorted(set(nums))) # [1, 2, 3, 4, 5]练习 4:
python
result = [x for x in range(1, 101) if x % 3 == 0 or x % 5 == 0]
print(result[:20]) # 前 20 个