Files
PythonLearn/01_python基础/1_11_集合/README.md

531 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第 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` 判断元素;
- 能正确添加、删除和遍历集合元素;
- 能计算两组集合的交集、并集、差集和对称差集;
- 能判断子集关系;
- 能使用集合完成列表去重;
- 示例和练习均可正常运行。