feat(python基础): 完成第十一至十三课教学内容

This commit is contained in:
zhiye.sun
2026-08-03 14:22:36 +08:00
parent b5023b8e25
commit 298e5b46ea
11 changed files with 1862 additions and 29 deletions

View File

@@ -0,0 +1,530 @@
# 第 1-11 课:集合
## 一、本课目标
完成本课后,你将能够:
1. 理解集合是什么,以及集合适合解决什么问题;
2. 使用 `{}``set()` 创建集合;
3. 理解集合中元素唯一、集合本身无序;
4. 使用 `add()``update()` 添加元素;
5. 使用 `remove()``discard()``pop()``clear()` 删除元素;
6. 使用 `in``not in` 判断元素是否存在;
7. 遍历集合;
8. 使用交集、并集、差集和对称差集;
9. 使用集合为列表去重;
10. 根据实际需求在列表、元组、字典和集合之间做出选择。
## 二、前置知识
学习本课前,应当已经了解:
- 变量与常见数据类型;
- 条件判断;
- `for` 循环;
- 字符串;
- 列表和元组;
- 字典;
- `in``not in`
## 三、集合是什么
集合Set是一种保存多个元素的数据结构。
它有两个非常重要的特点:
1. **元素不能重复**
2. **元素没有固定位置**
例如,一个 Agent 可以拥有多个工具权限:
```python
agent_tools = {"搜索", "计算", "写作"}
```
如果重复写入同一个工具,集合只会保留一份:
```python
agent_tools = {"搜索", "计算", "搜索"}
print(agent_tools)
```
集合中最终只有两个元素。
集合特别适合处理:
- 去除重复数据;
- 快速判断某个元素是否存在;
- 比较两组数据有哪些相同项或不同项;
- 权限、标签、课程、技能等不允许重复的数据。
## 四、创建集合
### 4.1 使用花括号创建
```python
agent_tools = {"搜索", "计算", "写作"}
print(agent_tools)
```
集合使用花括号,但它与字典不同:
```python
# 集合:里面直接保存元素
agent_tools = {"搜索", "计算"}
# 字典:里面保存“键: 值”
agent_config = {"model": "gpt-5", "enabled": True}
```
### 4.2 使用 `set()` 创建
```python
agent_tools = set(["搜索", "计算", "搜索"])
print(agent_tools)
```
`set()` 会把传入的数据转换成集合,并自动去除重复元素。
### 4.3 创建空集合
空集合必须写成:
```python
empty_tools = set()
```
不能写成:
```python
empty_tools = {}
```
因为 `{}` 创建的是空字典,不是空集合。
可以使用 `type()` 验证:
```python
print(type(set()))
print(type({}))
```
## 五、集合为什么不支持下标
列表和元组中的元素有明确位置,所以可以写:
```python
models = ["gpt-5", "o3"]
print(models[0])
```
集合是无序数据结构,不保证每个元素一直处于某个固定位置,因此不能写:
```python
agent_tools = {"搜索", "计算"}
print(agent_tools[0]) # 错误
```
这里的“无序”不是说 Python 每次一定用不同顺序显示,而是说:
> 不应该依赖集合元素的显示顺序,也不能使用下标读取集合元素。
如果业务需要稳定顺序,应使用列表或元组。
## 六、集合元素必须唯一
```python
models = {"gpt-5", "o3", "gpt-5"}
print(len(models))
```
结果为:
```text
2
```
第二个 `"gpt-5"` 不会产生新元素,也不会报错。
## 七、判断元素是否存在
集合经常配合 `in``not in` 使用:
```python
agent_tools = {"搜索", "计算"}
print("搜索" in agent_tools)
print("写作" not in agent_tools)
```
正常结果:
```text
True
True
```
集合非常擅长成员判断。数据较多时,通常比逐个检查列表更合适。
## 八、添加元素
### 8.1 使用 `add()` 添加一个元素
```python
agent_tools = {"搜索", "计算"}
agent_tools.add("写作")
print(agent_tools)
```
如果添加已经存在的元素,集合不会发生变化:
```python
agent_tools.add("搜索")
```
### 8.2 使用 `update()` 添加多个元素
```python
agent_tools = {"搜索"}
agent_tools.update(["计算", "写作"])
print(agent_tools)
```
注意:
- `add()` 添加一个完整元素;
- `update()` 从列表、元组、集合等可遍历数据中逐个取出元素并添加。
## 九、删除元素
### 9.1 `remove()`:元素不存在时会报错
```python
agent_tools = {"搜索", "计算"}
agent_tools.remove("搜索")
```
如果继续删除不存在的 `"搜索"`,会出现 `KeyError`,中文意思是找不到该元素。
### 9.2 `discard()`:元素不存在也不会报错
```python
agent_tools = {"搜索", "计算"}
agent_tools.discard("写作")
```
当你不确定元素是否存在时,`discard()` 通常更安全。
### 9.3 `pop()`:删除并返回一个不确定的元素
```python
agent_tools = {"搜索", "计算"}
removed_tool = agent_tools.pop()
print(removed_tool)
```
集合没有固定顺序,所以不能依赖 `pop()` 删除某个指定元素。
如果集合为空,调用 `pop()` 会报错。
### 9.4 `clear()`:清空集合
```python
agent_tools = {"搜索", "计算"}
agent_tools.clear()
print(agent_tools)
```
结果是空集合:
```text
set()
```
## 十、遍历集合
集合可以使用 `for` 循环遍历:
```python
agent_tools = {"搜索", "计算", "写作"}
for tool in agent_tools:
print(tool)
```
变量名 `tool` 可以换成其他合法名称,但应当选择能够表达含义的名字。
不要依赖遍历顺序。如果必须按顺序输出,可以先使用 `sorted()` 排序:
```python
for tool in sorted(agent_tools):
print(tool)
```
`sorted()` 会返回一个排好序的新列表,不会修改原集合。
## 十一、交集:两组数据共同拥有的元素
交集可以使用 `&``intersection()`
```python
code_agent_tools = {"搜索", "计算", "代码执行"}
writer_agent_tools = {"搜索", "写作", "图片生成"}
common_tools = code_agent_tools & writer_agent_tools
print(common_tools)
```
结果:
```text
{'搜索'}
```
也可以写成:
```python
common_tools = code_agent_tools.intersection(writer_agent_tools)
```
## 十二、并集:合并两组数据并自动去重
并集可以使用 `|``union()`
```python
all_tools = code_agent_tools | writer_agent_tools
print(all_tools)
```
结果包含两组集合的全部工具,重复的 `"搜索"` 只保留一份。
## 十三、差集:一组有、另一组没有的元素
差集使用 `-``difference()`
```python
code_only_tools = code_agent_tools - writer_agent_tools
print(code_only_tools)
```
它表示代码助手拥有、写作助手没有的工具。
注意方向:
```python
code_agent_tools - writer_agent_tools
```
和:
```python
writer_agent_tools - code_agent_tools
```
结果通常不同。
## 十四、对称差集:只属于其中一组的元素
对称差集使用 `^``symmetric_difference()`
```python
different_tools = code_agent_tools ^ writer_agent_tools
print(different_tools)
```
它会排除两组共同拥有的元素,只保留各自独有的元素。
## 十五、集合之间的关系判断
如果集合 A 中的所有元素都在集合 B 中A 就是 B 的子集:
```python
required_tools = {"搜索", "计算"}
available_tools = {"搜索", "计算", "写作"}
print(required_tools <= available_tools)
```
结果为 `True`
也可以使用:
```python
print(required_tools.issubset(available_tools))
print(available_tools.issuperset(required_tools))
```
- 子集Subset较小集合中的元素全部包含在较大集合中
- 超集Superset较大集合包含较小集合的全部元素。
这很适合判断“当前权限是否满足所需权限”。
## 十六、使用集合为列表去重
```python
model_history = ["gpt-5", "o3", "gpt-5", "o3", "gpt-5-mini"]
unique_models = set(model_history)
print(unique_models)
```
如果最终仍然需要列表,可以再转换:
```python
unique_model_list = list(unique_models)
```
注意:这种方法不保证保留原列表顺序。
当前阶段如果既要去重又要保留顺序,可以使用:
```python
unique_model_list = []
for model in model_history:
if model not in unique_model_list:
unique_model_list.append(model)
```
## 十七、哪些数据可以放入集合
集合元素必须是不可变且可哈希Hashable的数据。
当前阶段可以简单理解为:
- 字符串、数字、布尔值、元组通常可以放入集合;
- 列表、字典、普通集合不能直接放入集合。
下面会报错:
```python
invalid_set = {[1, 2], [3, 4]}
```
因为列表可以被修改,不能作为集合元素。
“哈希”的内部原理将在进阶阶段逐步补充,本课只需要记住常见规则。
## 十八、列表、元组、字典和集合如何选择
### 使用列表
- 需要保留顺序;
- 允许重复;
- 需要使用下标读取或修改。
### 使用元组
- 需要保留顺序;
- 允许重复;
- 创建后不希望修改整体结构。
### 使用字典
- 需要使用“键”描述每个“值”;
- 需要通过字段名称快速读取数据。
### 使用集合
- 不关心顺序;
- 不允许重复;
- 经常进行成员判断、去重或集合运算。
## 十九、运行本课示例
进入项目根目录:
```powershell
cd D:\Code\Python
```
运行示例:
```powershell
python .\01_python基础\1_11_集合\sets.py
```
运行练习:
```powershell
python .\01_python基础\1_11_集合\practice.py
```
集合的显示顺序可能与讲义不同,只要元素相同就是正常现象。
## 二十、常见错误
### 20.1 使用 `{}` 创建空集合
`{}` 是空字典,空集合必须使用 `set()`
### 20.2 使用下标读取集合
集合不支持下标。如果需要按位置读取,应使用列表或元组。
### 20.3 使用 `remove()` 删除不存在的元素
不确定元素是否存在时,可以先用 `in` 判断,或者使用 `discard()`
### 20.4 依赖集合的输出顺序
集合不保证业务上的稳定顺序。需要排序展示时使用 `sorted()`
### 20.5 把列表或字典放入集合
列表和字典是可变数据,不能作为集合元素。
### 20.6 混淆 `add()` 和 `update()`
`add()` 添加一个元素;`update()` 从其他可遍历数据中添加多个元素。
## 二十一、课堂练习
打开:
```text
01_python基础/1_11_集合/practice.py
```
本课练习将创建一个“Agent 工具权限管理器”,内容包括:
1. 创建集合;
2. 检查、添加和删除权限;
3. 遍历权限;
4. 比较两组权限的交集、并集、差集和对称差集;
5. 判断所需权限是否是可用权限的子集;
6. 为模型使用记录去重。
请先独立完成。遇到问题时,我会先给出定位提示,不会直接覆盖你的答案。
## 二十二、思考题
1. 为什么 `{}` 不能表示空集合?
2. 为什么不能使用 `agent_tools[0]` 读取集合?
3. `remove()``discard()` 有什么区别?
4. `A - B``B - A` 为什么可能不同?
5. 使用集合为列表去重时,可能丢失什么信息?
## 二十三、本课小结
本课最重要的知识点:
1. 集合使用 `set` 类型表示;
2. 集合元素唯一,且没有可依赖的固定顺序;
3. 空集合必须使用 `set()` 创建;
4. `add()` 添加一个元素,`update()` 添加多个元素;
5. `remove()` 删除不存在的元素会报错,`discard()` 不会;
6. 集合支持交集、并集、差集和对称差集;
7. 集合适合去重、成员判断和权限比较。
## 二十四、验收标准
完成练习后,应满足:
- 能正确创建非空集合和空集合;
- 能解释集合为什么不支持下标;
- 能使用 `in` 判断元素;
- 能正确添加、删除和遍历集合元素;
- 能计算两组集合的交集、并集、差集和对称差集;
- 能判断子集关系;
- 能使用集合完成列表去重;
- 示例和练习均可正常运行。