> 上节课我们搞定了环境搭建和基础语法,今天进入 Python 最强大的部分——数据结构。
---
## 一、为什么数据结构如此重要?
如果说变量是砖头,那数据结构就是钢筋水泥。学会数据结构,你才能:
1.**高效组织数据**——不再到处传零散变量
2.**利用内置方法**——Python 为每种数据结构提供了丰富的操作方法
3.**写出更 Pythonic 的代码**——列表推导式、字典推导式是 Python 的精髓
---
## 二、列表(List)—— Python 最常用的数据结构
### 2.1 列表的基础操作
```python
# 创建列表
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True] # Python 列表可以混装不同类型
# 索引访问(从0开始)
print(fruits[0]) # 苹果
print(fruits[-1]) # 葡萄(负索引表示从末尾数)
# 切片操作(超好用!)
print(fruits[1:3]) # ['香蕉', '橙子'](左闭右开)
print(fruits[:2]) # ['苹果', '香蕉'](省略前面相当于从0开始)
print(fruits[2:]) # ['橙子', '葡萄'](省略后面相当于到最后)
# 修改列表元素
fruits[1] = "芒果"
print(fruits) # ['苹果', '芒果', '橙子', '葡萄']
# 添加元素
fruits.append("西瓜") # 追加到末尾
fruits.insert(1, "草莓") # 插入到指定位置
fruits.extend(["樱桃", "蓝莓"]) # 批量追加
# 删除元素
fruits.remove("芒果") # 按值删除
popped = fruits.pop() # 弹出最后一个并返回
popped = fruits.pop(2) # 弹出指定位置的元素
del fruits[0] # 按索引删除(没有返回值)
# 列表长度
print(len(fruits)) # 剩余元素数量
# 查找元素
print(fruits.index("橙子")) # 返回索引位置
print("香蕉"in fruits) # True/False,判断是否存在
```
### 2.2 列表排序与反转
```python
names = ["张三", "李四", "王五", "赵六"]
numbers = [64, 34, 25, 71, 29, 90]
# 升序排列
numbers.sort()
print(numbers) # [25, 29, 34, 64, 71, 90]
# 降序排列
numbers.sort(reverse=True)
print(numbers) # [90, 71, 64, 34, 29, 25]
# 字母排序(中文按拼音/Unicode)
names.sort()
print(names)
# 反转(不排序,单纯倒过来)
numbers.reverse()
# 不修改原列表,返回新排序列表
original = [64, 34, 25, 71, 29, 90]
sorted_numbers = sorted(original)
print(sorted_numbers) # [25, 29, 34, 64, 71, 90]
print(original) # 原始列表不变
```
### 2.3 列表推导式(List Comprehension)—— Python 的灵魂语法
```python
# 普通写法:生成 0-9 的平方
squares = []
for x inrange(10):
squares.append(x ** 2)
# 推导式写法(一行搞定)
squares = [x ** 2for x inrange(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件过滤:只保留偶数的平方
even_squares = [x ** 2for x inrange(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
# 字符串操作:首字母大写
words = ["hello", "world", "python", "code"]
capitalized = [w.capitalize() for w in words]
print(capitalized) # ['Hello', 'World', 'Python', 'Code']
# 嵌套推导式:矩阵转置
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
transposed = [[row[i] for row in matrix] for i inrange(3)]
print(transposed) # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
# 实际应用:扁平化嵌套列表
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = [num for sublist in nested for num in sublist]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### 2.4 深浅拷贝
```python
# 浅拷贝:只复制第一层
original = [1, 2, [3, 4]]
shallow_copy = original.copy() # 或 list(original)
shallow_copy[2][0] = 99
print(original) # [1, 2, [99, 4]] ← 嵌套对象也被改了!
print(shallow_copy) # [1, 2, [99, 4]]
# 深拷贝:完全复制,互不影响
import copy
deep_copy = copy.deepcopy(original)
deep_copy[2][0] = 3
print(original) # [1, 2, [99, 4]] ← 不受影响
print(deep_copy) # [1, 2, [3, 4]]
```
---
## 三、元组(Tuple)—— 不可变的列表
```python
# 创建元组
rgb = (255, 128, 0)
coordinate = (3, 5)
single_element = (42,) # 注意:单个元素必须加逗号!
# 元组是不可变的(不能修改元素)
# rgb[0] = 100 ← 这会报错!TypeError
# 但可以用于:
# 1. 保护数据不被修改
# 2. 函数的多返回值
defget_user_info():
return"张三", 25, "北京"
name, age, city = get_user_info() # 解包赋值
print(f"{name},{age}岁,住在{city}")
# 3. 字典的键(列表不行,元组可以)
grades = {("数学", 2026): 95, ("英语", 2026): 88}
print(grades[("数学", 2026)]) # 95
```
---
## 四、字典(Dictionary)—— 键值对集合
### 4.1 字典基础
```python
# 创建字典
student = {
"name": "张三",
"age": 20,
"grade": "A",
"courses": ["数学", "物理", "化学"]
}
# 访问值
print(student["name"]) # 张三
print(student.get("email", "N/A")) # N/A(不会报错,键不存在返回默认值)
# 修改/添加
student["email"] = "zhangsan@example.com"
student["age"] = 21
# 删除
del student["grade"]
popped = student.pop("age") # 删除并返回值
# 遍历字典
for key, value in student.items():
print(f"{key}: {value}")
for key in student.keys():
print(key)
for value in student.values():
print(value)
# 检查键是否存在
print("email"in student) # True
```
### 4.2 字典推导式
```python
# 平方映射
squares_dict = {x: x**2for x inrange(1, 6)}
print(squares_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 从两个列表构建字典
names = ["Alice", "Bob", "Charlie"]
scores = [95, 87, 92]
score_dict = {name: score for name, score inzip(names, scores)}
print(score_dict) # {'Alice': 95, 'Bob': 87, 'Charlie': 92}
# 条件过滤
words = ["apple", "banana", "cherry", "date"]
short_words = {w: len(w) for w in words iflen(w) <= 5}
print(short_words) # {'apple': 5, 'date': 4}
```
### 4.3 字典实用技巧
```python
from collections import defaultdict, Counter
# defaultdict:访问不存在的键时自动创建默认值
scores = defaultdict(list)
scores["数学"].append(95)
scores["数学"].append(88)
scores["英语"].append(92)
print(dict(scores)) # {'数学': [95, 88], '英语': [92]}
# Counter:计数器,统计元素出现次数
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
word_counts = Counter(words)
print(word_counts) # Counter({'apple': 3, 'banana': 2, 'orange': 1})
print(word_counts.most_common(2)) # [('apple', 3), ('banana', 2)]
# 合并字典(Python 3.9+)
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
merged = {**dict1, **dict2} # {"a": 1, "b": 3, "c": 4}
merged = dict1 | dict2 # 等价写法
```
---
## 五、集合(Set)—— 去重与数学运算
```python
# 创建集合
fruits_a = {"苹果", "香蕉", "橙子"}
fruits_b = {"香蕉", "橙子", "葡萄"}
# 自动去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 5]
unique_numbers = set(numbers)
print(unique_numbers) # {1, 2, 3, 4, 5}
# 集合运算
print(fruits_a | fruits_b) # 并集:{'苹果', '香蕉', '橙子', '葡萄'}
print(fruits_a & fruits_b) # 交集:{'香蕉', '橙子'}
print(fruits_a - fruits_b) # 差集:{'苹果'}
print(fruits_a ^ fruits_b) # 对称差集:{'苹果', '葡萄'}(只出现在其中一个集合的元素)
# 添加/删除
fruits_a.add("西瓜")
fruits_a.update(["草莓", "蓝莓"])
fruits_a.remove("西瓜") # 删除不存在的元素会报错
fruits_a.discard("西瓜") # 更安全,不存在也不会报错
# 判断关系
subset = {1, 2}
superset = {1, 2, 3}
print(subset.issubset(superset)) # True
print(superset.issuperset(subset)) # True
```
---
## 六、字符串处理
### 6.1 字符串基础操作
```python
text = "Python is awesome"
# 基础方法
print(text.upper()) # PYTHON IS AWESOME
print(text.lower()) # python is awesome
print(text.title()) # Python Is Awesome
print(text.swapcase()) # pYTHON IS AWESOME
# 查找
print(text.find("awesome")) # 10
print(text.rfind("a")) # 16(从右边找)
print("xyz"in text) # False
# 替换
new_text = text.replace("awesome", "fantastic")
# 分割/拼接
sentence = "Python, is, awesome"
parts = sentence.split(",") # ['Python', ' is', ' awesome']
joined = " ".join(parts) # Python is awesome
# 去除空白
dirty_text = " hello world "
clean_text = dirty_text.strip() # 'hello world'
clean_left = dirty_text.lstrip() # 'hello world '
clean_right = dirty_text.rstrip() # ' hello world'
# 判断
print("abc123".isalpha()) # False(包含数字)
print("123".isdigit()) # True
print("ABC".isupper()) # True
print("".isspace()) # False
```
### 6.2 格式化字符串回顾
```python
name = "张三"
age = 25
score = 95.678
# f-string(推荐)
print(f"我叫{name},今年{age}岁,成绩{score:.1f}")
# 我叫张三,今年25岁,成绩95.7
# 对齐
print(f"|{'内容':<20}|") # |内容 |(左对齐)
print(f"|{'内容':>20}|") # | 内容|(右对齐)
print(f"|{'内容':^20}|") # | 内容 |(居中)
# 千位分隔符
print(f"{1234567:,.2f}") # 1,234,567.00
# 二进制/十六进制
print(f"{42:b}") # 101010(二进制)
print(f"{42:x}") # 2a(十六进制)
```
---
## 七、实战项目:联系人管理系统
```python
# 使用字典构建一个简单的联系人管理程序
contacts = {}
defadd_contact(name, phone):
if name in contacts:
print(f"⚠️ 联系人 {name} 已存在")
else:
contacts[name] = {"phone": phone}
print(f"✅ 已添加 {name}")
defsearch_contact(name):
if name in contacts:
info = contacts[name]
print(f"📱 {name}: {info['phone']}")
else:
print(f"❌ 未找到 {name}")
defdelete_contact(name):
if name in contacts:
del contacts[name]
print(f"🗑️ 已删除 {name}")
else:
print(f"❌ 未找到 {name}")
deflist_all_contacts():
ifnot contacts:
print("📭 通讯录为空")
return
print("\n" + "=" * 30)
print(f" 联系人总数:{len(contacts)}")
print("=" * 30)
for name, info insorted(contacts.items()):
print(f" {name}: {info['phone']}")
print("=" * 30)
# 演示
add_contact("张三", "13800138001")
add_contact("李四", "13800138002")
add_contact("王五", "13800138003")
list_all_contacts()
search_contact("张三")
delete_contact("王五")
list_all_contacts()
```
---
## 八、本节要点总结
| 数据结构 | 特点 | 适用场景 |
|---------|------|---------|
| **列表** | 有序、可重复、可变 | 需要修改/排序/过滤的数据集合 |
| **元组** | 有序、可重复、不可变 | 固定数据(如坐标、RGB颜色) |
| **字典** | 键值对、键唯一、查找快 | 需要通过标识符查找数据 |
| **集合** | 无序、不重复、支持集合运算 | 去重、交并差运算 |
---
## 九、练习题
### 练习 1:词频统计器
```python
text = "hello world hello python world hello"
words = text.split()
word_count = {}
for word in words:
word_count[word] = word_count.get(word, 0) + 1
# 按出现次数降序排序
sorted_words = sorted(word_count.items(), key=lambdax: x[1], reverse=True)
for word, count in sorted_words:
print(f"{word}: {count}次")
```
### 练习 2:矩阵转置
```python
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[matrix[row][col] for row inrange(len(matrix))]
for col inrange(len(matrix[0]))]
print(transposed)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
```
### 练习 3:去除列表中的重复项,保持顺序
```python
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
seen = set()
unique = []
for item in data:
if item notin seen:
seen.add(item)
unique.append(item)
print(unique) # [3, 1, 4, 5, 9, 2, 6]
```
### 练习 4:用字典模拟购物车
```python
cart = {}
products = {"苹果": 5.0, "香蕉": 3.0, "橙子": 4.5, "葡萄": 8.0}
# 添加商品
cart["苹果"] = cart.get("苹果", 0) + 2
cart["香蕉"] = cart.get("香蕉", 0) + 3
# 计算总价
total = sum(products[item] * quantity for item, quantity in cart.items())
for item, quantity in cart.items():
print(f"{item}: {quantity} x ¥{products[item]:.2f}")
print(f"总计: ¥{total:.2f}")
```
### 练习 5:简易学生成绩分析
```python
students = {
"张三": {"数学": 95, "英语": 88, "物理": 92},
"李四": {"数学": 78, "英语": 95, "物理": 85},
"王五": {"数学": 90, "英语": 72, "物理": 95},
}
# 计算各科平均分
subjects = ["数学", "英语", "物理"]
for subject in subjects:
scores = [student[subject] for student in students.values()]
avg = sum(scores) / len(scores)
print(f"{subject}平均分: {avg:.1f}分")
# 找出总分最高的学生
for name, scores in students.items():
total = sum(scores.values())
print(f"{name}总分: {total}")
```
---
## 下期预告
**Python 教程 Episode 03 — 面向对象编程**
- 类与对象:class、__init__、self
- 封装:属性与方法私有化
- 继承:子类与父类,super() 的使用
- 多态:不同类实现相同接口
- 魔术方法:__str__、__repr__、__len__、__eq__ 等
- 实战:构建一个简单的银行账户系统
---
*如果觉得本系列对你有帮助,欢迎点赞、评论、转发!有任何问题,在留言区讨论。*