feat(python基础): 完成第十一至十三课教学内容
This commit is contained in:
530
01_python基础/1_11_集合/README.md
Normal file
530
01_python基础/1_11_集合/README.md
Normal 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` 判断元素;
|
||||||
|
- 能正确添加、删除和遍历集合元素;
|
||||||
|
- 能计算两组集合的交集、并集、差集和对称差集;
|
||||||
|
- 能判断子集关系;
|
||||||
|
- 能使用集合完成列表去重;
|
||||||
|
- 示例和练习均可正常运行。
|
||||||
104
01_python基础/1_11_集合/practice.py
Normal file
104
01_python基础/1_11_集合/practice.py
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# 第 1-11 课课堂练习:Agent 工具权限管理器
|
||||||
|
#
|
||||||
|
# 完成要求:
|
||||||
|
# 1. 根据注释完成集合的创建、成员判断、添加、删除、遍历和集合运算。
|
||||||
|
# 2. 使用有意义的英文蛇形变量名。
|
||||||
|
# 3. 不要依赖集合的显示顺序。
|
||||||
|
# 4. 删除可能不存在的元素时使用 discard(),或先使用 in 判断。
|
||||||
|
# 5. 不要删除题目注释。
|
||||||
|
# 6. 完成后运行本文件并核对预期结果。
|
||||||
|
|
||||||
|
# 练习一:创建集合 agent_tools,包含以下工具:
|
||||||
|
# "搜索"、"计算"、"写作"、"搜索"。
|
||||||
|
# 输出集合和元素数量,观察重复的“搜索”是否只保留一份。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习二:创建空集合 disabled_tools。
|
||||||
|
# 输出它的值和类型,确认类型是 set,而不是 dict。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习三:完成成员判断:
|
||||||
|
# 1. 判断 agent_tools 中是否存在“搜索”,保存到 can_search;
|
||||||
|
# 2. 判断 agent_tools 中是否不存在“图片生成”,保存到 cannot_generate_image;
|
||||||
|
# 3. 输出两个判断结果。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习四:使用 add() 向 agent_tools 添加“代码执行”。
|
||||||
|
# 再次使用 add() 添加已经存在的“搜索”。
|
||||||
|
# 输出添加后的集合和元素数量,确认没有产生重复元素。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习五:使用 update() 一次添加“图片生成”和“网页浏览”。
|
||||||
|
# 传给 update() 的数据可以使用列表。
|
||||||
|
# 输出更新后的集合。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习六:完成安全删除:
|
||||||
|
# 1. 使用 remove() 删除确定存在的“网页浏览”;
|
||||||
|
# 2. 使用 discard() 删除不存在的“语音识别”;
|
||||||
|
# 3. 输出删除后的集合,确认程序没有报错。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习七:使用 for 遍历 agent_tools。
|
||||||
|
# 为了让输出顺序稳定,请遍历 sorted(agent_tools)。
|
||||||
|
# 每行按照“可用工具:搜索”的格式输出。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习八:创建两个集合:
|
||||||
|
# code_agent_tools = {"搜索", "计算", "代码执行"}
|
||||||
|
# writer_agent_tools = {"搜索", "写作", "图片生成"}
|
||||||
|
# 计算并输出:
|
||||||
|
# 1. 交集 common_tools;
|
||||||
|
# 2. 并集 all_tools;
|
||||||
|
# 3. 代码助手独有的差集 code_only_tools;
|
||||||
|
# 4. 对称差集 different_tools。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习九:创建以下两个集合:
|
||||||
|
# required_tools = {"搜索", "计算"}
|
||||||
|
# available_tools = {"搜索", "计算", "写作"}
|
||||||
|
# 使用 <= 判断 required_tools 是否是 available_tools 的子集,
|
||||||
|
# 将结果保存到 has_required_tools 并输出。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习十:为模型使用记录去重:
|
||||||
|
# model_history = ["gpt-5", "o3", "gpt-5", "o3", "gpt-5-mini"]
|
||||||
|
# 将列表转换成集合 unique_models 并输出;
|
||||||
|
# 再把集合转换成列表 unique_model_list 并输出。
|
||||||
|
# 注意:转换后的顺序可能与原列表不同。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习十一:创建集合 current_permissions:
|
||||||
|
# {"读取配置", "修改配置", "执行任务"}
|
||||||
|
# 再创建集合 revoked_permissions:
|
||||||
|
# {"修改配置", "删除配置"}
|
||||||
|
# 使用差集得到 remaining_permissions,
|
||||||
|
# 表示撤销相关权限后仍然保留的权限,并输出结果。
|
||||||
|
|
||||||
|
|
||||||
|
# 预期核心结果:
|
||||||
|
# agent_tools 中重复的“搜索”只保留一份;
|
||||||
|
# disabled_tools 的类型是 set;
|
||||||
|
# can_search = True;
|
||||||
|
# cannot_generate_image = True;
|
||||||
|
# 重复执行 add("搜索") 不会增加元素数量;
|
||||||
|
# discard() 删除不存在的元素时不会报错;
|
||||||
|
# common_tools = {"搜索"};
|
||||||
|
# all_tools 包含两组 Agent 的全部工具;
|
||||||
|
# code_only_tools = {"计算", "代码执行"};
|
||||||
|
# different_tools 不包含共同拥有的“搜索”;
|
||||||
|
# has_required_tools = True;
|
||||||
|
# unique_models 只有三个元素;
|
||||||
|
# remaining_permissions = {"读取配置", "执行任务"}。
|
||||||
|
|
||||||
|
|
||||||
|
# 完成后进行自查:
|
||||||
|
# 1. 空集合是否使用 set() 创建;
|
||||||
|
# 2. 是否理解集合会自动去除重复元素;
|
||||||
|
# 3. add() 和 update() 是否按要求分别使用;
|
||||||
|
# 4. 删除不存在的元素时是否避免了 KeyError;
|
||||||
|
# 5. 遍历时是否没有依赖集合自身的顺序;
|
||||||
|
# 6. 是否能区分交集、并集、差集和对称差集;
|
||||||
|
# 7. 是否理解差集运算的左右方向;
|
||||||
|
# 8. 是否能使用子集判断检查权限;
|
||||||
|
# 9. 是否理解集合去重可能打乱原列表顺序。
|
||||||
116
01_python基础/1_11_集合/sets.py
Normal file
116
01_python基础/1_11_集合/sets.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# 第 1-11 课示例:集合
|
||||||
|
#
|
||||||
|
# 本文件集中演示集合的创建、成员判断、增删、遍历和集合运算。
|
||||||
|
# 集合没有可依赖的固定顺序,因此你看到的元素显示顺序可能不同。
|
||||||
|
|
||||||
|
|
||||||
|
print("一、创建集合")
|
||||||
|
|
||||||
|
# 集合使用花括号保存多个不重复的元素。
|
||||||
|
agent_tools = {"搜索", "计算", "写作"}
|
||||||
|
print(f"Agent 工具:{agent_tools}")
|
||||||
|
print(f"工具数量:{len(agent_tools)}")
|
||||||
|
|
||||||
|
# 重复元素只会保留一份。
|
||||||
|
models = {"gpt-5", "o3", "gpt-5"}
|
||||||
|
print(f"自动去重后的模型:{models}")
|
||||||
|
|
||||||
|
# 空集合必须使用 set(),因为 {} 表示空字典。
|
||||||
|
empty_tools = set()
|
||||||
|
print(f"空集合:{empty_tools}")
|
||||||
|
print(f"空集合类型:{type(empty_tools)}")
|
||||||
|
print(f"空字典类型:{type({})}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n二、成员判断")
|
||||||
|
|
||||||
|
print(f"是否拥有搜索工具:{'搜索' in agent_tools}")
|
||||||
|
print(f"是否没有图片生成工具:{'图片生成' not in agent_tools}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n三、添加元素")
|
||||||
|
|
||||||
|
# add() 每次添加一个元素。
|
||||||
|
agent_tools.add("代码执行")
|
||||||
|
print(f"添加一个工具后:{agent_tools}")
|
||||||
|
|
||||||
|
# 重复添加不会报错,也不会产生重复元素。
|
||||||
|
agent_tools.add("搜索")
|
||||||
|
print(f"重复添加搜索后:{agent_tools}")
|
||||||
|
|
||||||
|
# update() 可以从列表等可遍历数据中添加多个元素。
|
||||||
|
agent_tools.update(["图片生成", "网页浏览"])
|
||||||
|
print(f"添加多个工具后:{agent_tools}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n四、删除元素")
|
||||||
|
|
||||||
|
# remove() 用于删除确定存在的元素。
|
||||||
|
agent_tools.remove("网页浏览")
|
||||||
|
print(f"remove() 删除后:{agent_tools}")
|
||||||
|
|
||||||
|
# discard() 在元素不存在时也不会报错。
|
||||||
|
agent_tools.discard("不存在的工具")
|
||||||
|
print(f"discard() 安全删除后:{agent_tools}")
|
||||||
|
|
||||||
|
# pop() 会删除并返回一个不确定的元素。
|
||||||
|
# 因为集合无序,不应猜测它会删除哪一个。
|
||||||
|
temporary_tools = {"工具甲", "工具乙"}
|
||||||
|
removed_tool = temporary_tools.pop()
|
||||||
|
print(f"pop() 删除的元素:{removed_tool}")
|
||||||
|
print(f"pop() 删除后的集合:{temporary_tools}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n五、遍历集合")
|
||||||
|
|
||||||
|
# sorted() 会返回排好序的新列表,方便得到稳定的展示结果。
|
||||||
|
for tool in sorted(agent_tools):
|
||||||
|
print(f"可用工具:{tool}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n六、集合运算")
|
||||||
|
|
||||||
|
code_agent_tools = {"搜索", "计算", "代码执行"}
|
||||||
|
writer_agent_tools = {"搜索", "写作", "图片生成"}
|
||||||
|
|
||||||
|
# 交集:两组集合共同拥有的元素。
|
||||||
|
common_tools = code_agent_tools & writer_agent_tools
|
||||||
|
print(f"共同工具:{common_tools}")
|
||||||
|
|
||||||
|
# 并集:两组集合的全部元素,重复项只保留一份。
|
||||||
|
all_tools = code_agent_tools | writer_agent_tools
|
||||||
|
print(f"全部工具:{all_tools}")
|
||||||
|
|
||||||
|
# 差集:左侧集合有、右侧集合没有的元素。
|
||||||
|
code_only_tools = code_agent_tools - writer_agent_tools
|
||||||
|
writer_only_tools = writer_agent_tools - code_agent_tools
|
||||||
|
print(f"代码助手独有工具:{code_only_tools}")
|
||||||
|
print(f"写作助手独有工具:{writer_only_tools}")
|
||||||
|
|
||||||
|
# 对称差集:只属于其中一组、不属于两组公共部分的元素。
|
||||||
|
different_tools = code_agent_tools ^ writer_agent_tools
|
||||||
|
print(f"两组不同的工具:{different_tools}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n七、子集与超集")
|
||||||
|
|
||||||
|
required_tools = {"搜索", "计算"}
|
||||||
|
available_tools = {"搜索", "计算", "写作"}
|
||||||
|
|
||||||
|
has_required_tools = required_tools <= available_tools
|
||||||
|
print(f"现有权限是否满足要求:{has_required_tools}")
|
||||||
|
print(f"required_tools 是否为子集:{required_tools.issubset(available_tools)}")
|
||||||
|
print(f"available_tools 是否为超集:{available_tools.issuperset(required_tools)}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n八、使用集合去重")
|
||||||
|
|
||||||
|
model_history = ["gpt-5", "o3", "gpt-5", "o3", "gpt-5-mini"]
|
||||||
|
unique_models = set(model_history)
|
||||||
|
print(f"原始模型记录:{model_history}")
|
||||||
|
print(f"去重后的模型集合:{unique_models}")
|
||||||
|
|
||||||
|
# 如果后续操作必须使用列表,可以通过 list() 转换回来。
|
||||||
|
# 转换后的列表不保证保留原列表的先后顺序。
|
||||||
|
unique_model_list = list(unique_models)
|
||||||
|
print(f"转换后的模型列表:{unique_model_list}")
|
||||||
300
01_python基础/1_12_函数/README.md
Normal file
300
01_python基础/1_12_函数/README.md
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
# 第 1-12 课:函数
|
||||||
|
|
||||||
|
## 一、本课目标
|
||||||
|
|
||||||
|
完成本课后,你将能够:
|
||||||
|
|
||||||
|
1. 理解函数是什么,以及为什么需要函数;
|
||||||
|
2. 使用 `def` 定义函数;
|
||||||
|
3. 调用函数并传递参数;
|
||||||
|
4. 使用返回值把结果交给调用者;
|
||||||
|
5. 区分“打印结果”和“返回结果”;
|
||||||
|
6. 使用默认参数和关键字参数;
|
||||||
|
7. 理解局部变量和全局变量的基本区别;
|
||||||
|
8. 为简单函数编写文档字符串;
|
||||||
|
9. 把重复代码整理成可复用的函数。
|
||||||
|
|
||||||
|
## 二、前置知识
|
||||||
|
|
||||||
|
- 变量和数据类型;
|
||||||
|
- 条件判断;
|
||||||
|
- `for` 循环;
|
||||||
|
- 字符串、列表、字典和集合;
|
||||||
|
- 基本的布尔判断。
|
||||||
|
|
||||||
|
## 三、函数是什么
|
||||||
|
|
||||||
|
函数(Function)是一段有名字、可以重复执行的代码。
|
||||||
|
|
||||||
|
例如,下面的代码每次都能完成同一件事:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def say_hello():
|
||||||
|
print("你好,Python!")
|
||||||
|
```
|
||||||
|
|
||||||
|
定义函数不会立即执行函数体。只有调用它时,代码才会运行:
|
||||||
|
|
||||||
|
```python
|
||||||
|
say_hello()
|
||||||
|
```
|
||||||
|
|
||||||
|
可以把函数理解为一个“工具盒”:
|
||||||
|
|
||||||
|
- 定义函数:制作工具;
|
||||||
|
- 调用函数:使用工具;
|
||||||
|
- 参数:交给工具的材料;
|
||||||
|
- 返回值:工具加工后的结果。
|
||||||
|
|
||||||
|
## 四、定义和调用函数
|
||||||
|
|
||||||
|
基本格式:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def 函数名():
|
||||||
|
函数体
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:
|
||||||
|
|
||||||
|
1. `def` 是定义函数的关键字;
|
||||||
|
2. 函数名建议使用英文蛇形命名;
|
||||||
|
3. 函数体必须缩进;
|
||||||
|
4. 函数定义后需要通过 `函数名()` 调用。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def print_separator():
|
||||||
|
print("=" * 30)
|
||||||
|
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 五、参数:把数据交给函数
|
||||||
|
|
||||||
|
### 5.1 一个参数
|
||||||
|
|
||||||
|
```python
|
||||||
|
def greet_user(name):
|
||||||
|
print(f"你好,{name}!")
|
||||||
|
|
||||||
|
|
||||||
|
greet_user("小明")
|
||||||
|
```
|
||||||
|
|
||||||
|
`name` 是参数(Parameter),`"小明"` 是调用时传入的实参(Argument)。
|
||||||
|
|
||||||
|
### 5.2 多个参数
|
||||||
|
|
||||||
|
```python
|
||||||
|
def print_agent(name, model):
|
||||||
|
print(f"Agent:{name},模型:{model}")
|
||||||
|
|
||||||
|
|
||||||
|
print_agent("代码助手", "gpt-5")
|
||||||
|
```
|
||||||
|
|
||||||
|
参数按位置传递时,顺序很重要。
|
||||||
|
|
||||||
|
### 5.3 关键字参数
|
||||||
|
|
||||||
|
也可以明确写出参数名:
|
||||||
|
|
||||||
|
```python
|
||||||
|
print_agent(model="gpt-5", name="代码助手")
|
||||||
|
```
|
||||||
|
|
||||||
|
使用关键字参数后,调用顺序可以调整,可读性也更好。
|
||||||
|
|
||||||
|
## 六、返回值:把结果交给调用者
|
||||||
|
|
||||||
|
`return` 用于结束函数执行,并把结果返回给调用者:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def add_numbers(first_number, second_number):
|
||||||
|
return first_number + second_number
|
||||||
|
|
||||||
|
|
||||||
|
total = add_numbers(3, 5)
|
||||||
|
print(total)
|
||||||
|
```
|
||||||
|
|
||||||
|
`return` 后面的结果可以保存到变量、参与计算或传给其他函数。
|
||||||
|
|
||||||
|
## 七、打印和返回的区别
|
||||||
|
|
||||||
|
下面两个函数看起来相似,但用途不同:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def print_total(first_number, second_number):
|
||||||
|
print(first_number + second_number)
|
||||||
|
|
||||||
|
|
||||||
|
def get_total(first_number, second_number):
|
||||||
|
return first_number + second_number
|
||||||
|
```
|
||||||
|
|
||||||
|
前者只负责显示,调用者不能直接拿到计算结果;后者把结果交给调用者,更适合程序继续处理。
|
||||||
|
|
||||||
|
```python
|
||||||
|
result = get_total(3, 5)
|
||||||
|
print(result * 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
如果函数没有写 `return`,Python 会自动返回 `None`,表示“没有结果”。
|
||||||
|
|
||||||
|
## 八、默认参数
|
||||||
|
|
||||||
|
可以为参数准备默认值:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def create_agent(name, model="gpt-5"):
|
||||||
|
return f"{name} 使用 {model}"
|
||||||
|
|
||||||
|
|
||||||
|
print(create_agent("代码助手"))
|
||||||
|
print(create_agent("搜索助手", "o3"))
|
||||||
|
```
|
||||||
|
|
||||||
|
调用时不传 `model`,就使用 `"gpt-5"`;传入了新值,就使用新值。
|
||||||
|
|
||||||
|
默认参数通常放在普通参数后面。
|
||||||
|
|
||||||
|
## 九、函数中的条件和循环
|
||||||
|
|
||||||
|
函数体可以包含前面学过的条件和循环:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count_enabled_agents(agents):
|
||||||
|
enabled_count = 0
|
||||||
|
|
||||||
|
for agent in agents:
|
||||||
|
if agent["enabled"]:
|
||||||
|
enabled_count += 1
|
||||||
|
|
||||||
|
return enabled_count
|
||||||
|
```
|
||||||
|
|
||||||
|
函数的价值之一,就是把一段有明确目的的处理逻辑集中起来。
|
||||||
|
|
||||||
|
## 十、变量作用域
|
||||||
|
|
||||||
|
作用域(Scope)表示变量可以被使用的范围。
|
||||||
|
|
||||||
|
```python
|
||||||
|
message = "这是全局变量"
|
||||||
|
|
||||||
|
|
||||||
|
def show_message():
|
||||||
|
local_message = "这是局部变量"
|
||||||
|
print(message)
|
||||||
|
print(local_message)
|
||||||
|
|
||||||
|
|
||||||
|
show_message()
|
||||||
|
```
|
||||||
|
|
||||||
|
- 在函数外定义的变量通常称为全局变量;
|
||||||
|
- 在函数内定义的变量通常是局部变量;
|
||||||
|
- 函数执行结束后,局部变量通常不能在函数外直接使用。
|
||||||
|
|
||||||
|
入门阶段建议:通过参数传入数据,通过 `return` 返回结果,少依赖全局变量。
|
||||||
|
|
||||||
|
## 十一、文档字符串
|
||||||
|
|
||||||
|
函数第一行的字符串可以作为文档字符串(Docstring),说明函数的用途:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def is_agent_enabled(agent):
|
||||||
|
"""判断 Agent 是否处于启用状态。"""
|
||||||
|
return agent["enabled"]
|
||||||
|
```
|
||||||
|
|
||||||
|
文档字符串会帮助自己和其他开发者理解函数。
|
||||||
|
|
||||||
|
## 十二、运行本课示例
|
||||||
|
|
||||||
|
进入项目根目录:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd D:\Code\Python
|
||||||
|
```
|
||||||
|
|
||||||
|
运行示例:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python .\01_python基础\1_12_函数\functions.py
|
||||||
|
```
|
||||||
|
|
||||||
|
运行练习:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python .\01_python基础\1_12_函数\practice.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 十三、常见错误
|
||||||
|
|
||||||
|
### 13.1 忘记调用函数
|
||||||
|
|
||||||
|
只写 `def` 是定义,不会自动执行,必须写 `函数名()`。
|
||||||
|
|
||||||
|
### 13.2 函数体没有缩进
|
||||||
|
|
||||||
|
`def` 下一行开始的函数体必须缩进,通常使用四个空格。
|
||||||
|
|
||||||
|
### 13.3 参数数量不匹配
|
||||||
|
|
||||||
|
函数需要两个参数却只传一个,会出现 `TypeError`,中文意思是参数数量或类型不正确。
|
||||||
|
|
||||||
|
### 13.4 把 `print()` 当成 `return`
|
||||||
|
|
||||||
|
`print()` 负责显示,`return` 负责把结果交给调用者。
|
||||||
|
|
||||||
|
### 13.5 忘记接收返回值
|
||||||
|
|
||||||
|
函数返回的结果如果后续还要使用,应保存到变量中。
|
||||||
|
|
||||||
|
### 13.6 过度使用全局变量
|
||||||
|
|
||||||
|
优先使用参数和返回值传递数据,让函数更容易测试和复用。
|
||||||
|
|
||||||
|
## 十四、课堂练习
|
||||||
|
|
||||||
|
打开:
|
||||||
|
|
||||||
|
```text
|
||||||
|
01_python基础/1_12_函数/practice.py
|
||||||
|
```
|
||||||
|
|
||||||
|
本课练习将创建“Agent 文本处理工具箱”,逐步完成:
|
||||||
|
|
||||||
|
1. 无参数问候函数;
|
||||||
|
2. 带参数的 Agent 信息函数;
|
||||||
|
3. 返回字符串的函数;
|
||||||
|
4. 带默认参数的配置函数;
|
||||||
|
5. 使用条件和循环统计 Agent;
|
||||||
|
6. 使用函数整理工具权限和模型记录。
|
||||||
|
|
||||||
|
## 十五、本课小结
|
||||||
|
|
||||||
|
1. 函数是可重复使用的代码块;
|
||||||
|
2. `def` 定义函数,调用函数时使用括号;
|
||||||
|
3. 参数用于输入数据;
|
||||||
|
4. `return` 用于返回结果;
|
||||||
|
5. `print()` 和 `return` 的用途不同;
|
||||||
|
6. 默认参数可以减少重复传值;
|
||||||
|
7. 局部变量和全局变量的作用范围不同;
|
||||||
|
8. 函数应尽量职责单一、名称清晰。
|
||||||
|
|
||||||
|
## 十六、验收标准
|
||||||
|
|
||||||
|
- 能独立定义并调用函数;
|
||||||
|
- 能正确传递一个或多个参数;
|
||||||
|
- 能区分打印和返回;
|
||||||
|
- 能使用默认参数;
|
||||||
|
- 能从函数外接收返回值;
|
||||||
|
- 能使用函数处理列表或字典;
|
||||||
|
- 示例和练习均可正常运行;
|
||||||
|
- 函数名和变量名符合英文蛇形命名规范。
|
||||||
56
01_python基础/1_12_函数/functions.py
Normal file
56
01_python基础/1_12_函数/functions.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# 第 1-12 课示例:函数
|
||||||
|
#
|
||||||
|
# 本文件演示函数的定义、调用、参数、返回值、默认参数和实际数据处理。
|
||||||
|
|
||||||
|
|
||||||
|
def print_separator():
|
||||||
|
"""输出分隔线,让命令行结果更容易阅读。"""
|
||||||
|
print("=" * 30)
|
||||||
|
|
||||||
|
|
||||||
|
def greet_user(name):
|
||||||
|
"""根据姓名输出问候语。"""
|
||||||
|
print(f"你好,{name}!")
|
||||||
|
|
||||||
|
|
||||||
|
def build_agent_description(name, model="gpt-5"):
|
||||||
|
"""返回 Agent 的文字描述,而不是直接打印。"""
|
||||||
|
return f"Agent:{name},模型:{model}"
|
||||||
|
|
||||||
|
|
||||||
|
def count_enabled_agents(agents):
|
||||||
|
"""统计列表中 enabled 为 True 的 Agent 数量。"""
|
||||||
|
enabled_count = 0
|
||||||
|
|
||||||
|
for agent in agents:
|
||||||
|
if agent["enabled"]:
|
||||||
|
enabled_count += 1
|
||||||
|
|
||||||
|
return enabled_count
|
||||||
|
|
||||||
|
|
||||||
|
def get_available_tools(agent):
|
||||||
|
"""返回 Agent 的工具列表;没有 tools 时返回空列表。"""
|
||||||
|
return agent.get("tools", [])
|
||||||
|
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
greet_user("Python 学习者")
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
print(build_agent_description("代码助手"))
|
||||||
|
print(build_agent_description("搜索助手", model="o3"))
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
agents = [
|
||||||
|
{"name": "代码助手", "enabled": True, "tools": ["搜索", "计算"]},
|
||||||
|
{"name": "搜索助手", "enabled": False, "tools": ["搜索"]},
|
||||||
|
{"name": "写作助手", "enabled": True, "tools": ["写作"]},
|
||||||
|
]
|
||||||
|
|
||||||
|
enabled_count = count_enabled_agents(agents)
|
||||||
|
print(f"启用的 Agent 数量:{enabled_count}")
|
||||||
|
|
||||||
|
for agent in agents:
|
||||||
|
tools = get_available_tools(agent)
|
||||||
|
print(f"{agent['name']} 的工具:{tools}")
|
||||||
145
01_python基础/1_12_函数/practice.py
Normal file
145
01_python基础/1_12_函数/practice.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# 第 1-12 课课堂练习:Agent 文本处理工具箱
|
||||||
|
#
|
||||||
|
# 完成要求:
|
||||||
|
# 1. 根据注释定义和调用函数,练习参数与返回值。
|
||||||
|
# 2. 使用有意义的英文蛇形函数名和变量名。
|
||||||
|
# 3. 函数体使用四个空格缩进。
|
||||||
|
# 4. 不要删除题目注释。
|
||||||
|
# 5. 完成后运行本文件并核对预期结果。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习一:定义并调用一个负责输出问候语的函数。
|
||||||
|
# 1. 定义 greet_user(name) 函数,参数 name 表示需要问候的姓名。
|
||||||
|
# 2. 函数内部使用 print() 输出“你好,{name}!”,本题不需要使用 return。
|
||||||
|
# 3. 调用函数时传入字符串“Python 学习者”。
|
||||||
|
# 4. 预期输出:你好,Python 学习者!
|
||||||
|
# 可参考 functions.py 中 greet_user(name) 的写法。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习二:定义一个用于生成 Agent 描述文本的函数。
|
||||||
|
# 1. 定义 build_agent_description(name, model) 函数。
|
||||||
|
# 参数 name 表示 Agent 名称,参数 model 表示模型名称。
|
||||||
|
# 2. 函数内部不要直接输出,而是使用 return 返回字符串:
|
||||||
|
# “Agent:{name},模型:{model}”。
|
||||||
|
# 3. 使用“代码助手”和“gpt-5”作为参数调用函数。
|
||||||
|
# 4. 把返回值保存到变量 description,再使用 print(description) 输出。
|
||||||
|
# 5. 预期输出:Agent:代码助手,模型:gpt-5
|
||||||
|
# 可参考 functions.py 中 build_agent_description(name, model) 的写法。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 练习三:定义一个计算两个数字之和的函数。
|
||||||
|
# 1. 定义 get_total(first_number, second_number) 函数,两个参数都接收数字。
|
||||||
|
# 2. 在函数内部计算 first_number + second_number,并使用 return 返回计算结果。
|
||||||
|
# 3. 调用函数计算 12 和 8,把返回值保存到变量 total。
|
||||||
|
# 4. 使用 print(total) 输出结果,预期输出:20。
|
||||||
|
# 注意:本题要练习返回值,因此不要只在函数内部 print() 计算结果。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 练习四:定义一个带默认参数的 Agent 描述函数。
|
||||||
|
# 1. 定义 build_agent_description_with_default(name, model="gpt-5") 函数。
|
||||||
|
# 2. 函数使用 return 返回“Agent:{name},模型:{model}”。
|
||||||
|
# 3. 第一次只传入 name="代码助手",把返回值保存并输出;此时 model 自动使用“gpt-5”。
|
||||||
|
# 4. 第二次传入 name="代码助手"和关键字参数 model="o3",再保存并输出返回值。
|
||||||
|
# 5. 两次预期输出分别为:
|
||||||
|
# Agent:代码助手,模型:gpt-5
|
||||||
|
# Agent:代码助手,模型:o3
|
||||||
|
# 可参考 functions.py 中默认参数和关键字参数的示例。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 练习五:定义一个安全读取 Agent 工具列表的函数。
|
||||||
|
# 1. 定义 get_agent_tools(agent) 函数,参数 agent 接收一个字典。
|
||||||
|
# 2. 函数内部使用 return agent.get("tools", []):
|
||||||
|
# 字典存在 tools 键时返回对应的列表,不存在时返回默认的空列表 []。
|
||||||
|
# 3. 创建第一个测试字典:
|
||||||
|
# {"name": "代码助手", "tools": ["搜索", "计算器"]}
|
||||||
|
# 4. 创建第二个测试字典:{"name": "聊天助手"},它没有 tools 键。
|
||||||
|
# 5. 分别调用函数并用 print() 输出返回值。
|
||||||
|
# 6. 两次预期输出分别为:["搜索", "计算器"] 和 []。
|
||||||
|
# 可参考 functions.py 中 get_available_tools(agent) 的写法。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 练习六:定义一个统计已启用 Agent 数量的函数。
|
||||||
|
# 1. 定义 count_enabled_agents(agents) 函数,参数 agents 接收“由字典组成的列表”。
|
||||||
|
# 2. 在函数内先创建计数变量 enabled_count,并把初始值设为 0。
|
||||||
|
# 3. 遍历 agents;如果当前字典的 agent["enabled"] 为 True,就把计数加 1。
|
||||||
|
# 4. 遍历结束后,使用 return 返回 enabled_count。不要遇到 False 就提前结束循环。
|
||||||
|
# 5. 使用下面三条数据测试:
|
||||||
|
# {"name": "代码助手", "enabled": True}
|
||||||
|
# {"name": "聊天助手", "enabled": False}
|
||||||
|
# {"name": "搜索助手", "enabled": True}
|
||||||
|
# 6. 保存并输出函数返回值,预期输出:2。
|
||||||
|
# 可参考 functions.py 中 count_enabled_agents(agents) 的写法。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 练习七:定义一个获取所有已启用 Agent 名称的函数。
|
||||||
|
# 1. 定义 get_enabled_agent_names(agents) 函数,agents 的数据结构与练习六相同。
|
||||||
|
# 2. 在函数内创建空列表 enabled_names,用于保存符合条件的名称。
|
||||||
|
# 3. 遍历 agents;当 agent["enabled"] 为 True 时,把 agent["name"] 添加到列表。
|
||||||
|
# 4. 遍历结束后,使用 return 返回 enabled_names。
|
||||||
|
# 5. 使用练习六给出的三条 Agent 数据调用函数,并使用 print() 输出返回值。
|
||||||
|
# 6. 预期输出:["代码助手", "搜索助手"],停用的“聊天助手”不应出现在结果中。
|
||||||
|
|
||||||
|
# 练习八:定义一个判断 Agent 是否具备全部必需工具的函数。
|
||||||
|
# 1. 定义 has_required_tools(agent, required_tools) 函数:
|
||||||
|
# agent 接收 Agent 字典,required_tools 接收“必需工具集合”。
|
||||||
|
# 2. 使用 agent.get("tools", []) 读取工具列表,再用 set() 转换为集合,
|
||||||
|
# 并把这个集合保存到局部变量 agent_tools。
|
||||||
|
# 3. 使用 required_tools <= agent_tools 判断“必需工具集合是否为 Agent 工具集合的子集”。
|
||||||
|
# 只有每一个必需工具都存在时,表达式才会得到 True。
|
||||||
|
# 4. 使用 return 返回判断结果,不要只在函数内部输出。
|
||||||
|
# 5. 创建测试 Agent:
|
||||||
|
# {"name": "代码助手", "tools": ["搜索", "计算器", "终端"]}
|
||||||
|
# 6. 第一次传入必需工具集合 {"搜索", "终端"},保存并输出结果,预期为 True。
|
||||||
|
# 7. 第二次传入必需工具集合 {"搜索", "数据库"},保存并输出结果,预期为 False。
|
||||||
|
# 可回顾上一课“集合”中的子集判断,也可参考本课练习五的字典读取方式。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习九:定义一个逐行输出 Agent 报告的函数。
|
||||||
|
# 1. 定义 print_agent_report(agents) 函数,agents 接收“由字典组成的列表”。
|
||||||
|
# 2. 每个字典都包含 name、enabled 和 tools 三个键,例如:
|
||||||
|
# {"name": "代码助手", "enabled": True, "tools": ["搜索", "终端"]}
|
||||||
|
# {"name": "聊天助手", "enabled": False, "tools": []}
|
||||||
|
# 3. 遍历 agents,根据 enabled 的布尔值生成中文状态:True 对应“启用”,False 对应“停用”。
|
||||||
|
# 4. 使用 len(agent["tools"]) 取得工具数量。
|
||||||
|
# 5. 在函数内部使用 print() 输出每个 Agent,本题只负责显示报告,不需要 return。
|
||||||
|
# 6. 调用函数后,预期输出:
|
||||||
|
# 代码助手:启用,工具数量:2
|
||||||
|
# 聊天助手:停用,工具数量:0
|
||||||
|
|
||||||
|
|
||||||
|
# 练习十:定义一个对模型使用记录去重并排序的函数。
|
||||||
|
# 1. 定义 normalize_model_history(model_history) 函数,参数接收模型名称列表。
|
||||||
|
# 2. 先使用 set(model_history) 去除重复名称。
|
||||||
|
# 3. 再把去重后的集合传给 sorted();sorted() 会返回一个排好序的新列表。
|
||||||
|
# 4. 使用 return 返回这个新列表,不要只在函数内部输出。
|
||||||
|
# 5. 使用 ["gpt-5", "o3", "gpt-5", "claude"] 调用函数,保存并输出返回值。
|
||||||
|
# 6. 预期输出:["claude", "gpt-5", "o3"]。
|
||||||
|
# 可回顾上一课“集合”中的去重方式和 sorted() 的用法。
|
||||||
|
|
||||||
|
|
||||||
|
# 预期核心结果:
|
||||||
|
# greet_user() 能输出问候语;
|
||||||
|
# build_agent_description() 能返回可保存的字符串;
|
||||||
|
# get_total(12, 8) 返回 20;
|
||||||
|
# 默认参数调用时使用 gpt-5,关键字参数调用时使用 o3;
|
||||||
|
# 没有 tools 的 Agent 返回空列表;
|
||||||
|
# count_enabled_agents() 返回 2;
|
||||||
|
# get_enabled_agent_names() 只返回启用 Agent 的名称;
|
||||||
|
# 权限满足判断返回 True;
|
||||||
|
# 报告函数能正确输出每个 Agent 的状态和工具数量;
|
||||||
|
# 模型记录去重后按排序结果返回。
|
||||||
|
|
||||||
|
|
||||||
|
# 完成后进行自查:
|
||||||
|
# 1. 是否使用 def 定义函数;
|
||||||
|
# 2. 是否正确传递位置参数和关键字参数;
|
||||||
|
# 3. 需要继续使用的结果是否使用 return;
|
||||||
|
# 4. 是否区分 print() 和 return;
|
||||||
|
# 5. 默认参数是否放在普通参数后面;
|
||||||
|
# 6. 函数内的局部变量是否没有误当作全局变量;
|
||||||
|
# 7. 函数是否尽量只负责一个清晰的任务。
|
||||||
381
01_python基础/1_13_函数进阶/README.md
Normal file
381
01_python基础/1_13_函数进阶/README.md
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
# 第 1-13 课:函数进阶
|
||||||
|
|
||||||
|
## 一、本课目标
|
||||||
|
|
||||||
|
完成本课后,你将能够:
|
||||||
|
|
||||||
|
1. 使用 `return` 一次返回多个结果;
|
||||||
|
2. 使用提前返回减少不必要的嵌套;
|
||||||
|
3. 使用 `*args` 接收任意数量的位置参数;
|
||||||
|
4. 使用 `**kwargs` 接收任意数量的关键字参数;
|
||||||
|
5. 使用 `*` 和 `**` 在调用函数时解包数据;
|
||||||
|
6. 根据不同任务选择普通参数、`*args` 或 `**kwargs`;
|
||||||
|
7. 继续练习让函数保持清晰、职责单一。
|
||||||
|
|
||||||
|
## 二、前置知识
|
||||||
|
|
||||||
|
学习本课前,需要理解:
|
||||||
|
|
||||||
|
- 如何使用 `def` 定义函数;
|
||||||
|
- 如何调用函数;
|
||||||
|
- 位置参数、关键字参数和默认参数;
|
||||||
|
- `print()` 与 `return` 的区别;
|
||||||
|
- 列表、元组和字典;
|
||||||
|
- 条件判断和循环。
|
||||||
|
|
||||||
|
## 三、一次返回多个结果
|
||||||
|
|
||||||
|
一个函数可以在 `return` 后面写多个值:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_agent_summary(agent):
|
||||||
|
return agent["name"], len(agent.get("tools", []))
|
||||||
|
|
||||||
|
|
||||||
|
agent_name, tool_count = get_agent_summary({
|
||||||
|
"name": "代码助手",
|
||||||
|
"tools": ["搜索", "终端"],
|
||||||
|
})
|
||||||
|
|
||||||
|
print(agent_name)
|
||||||
|
print(tool_count)
|
||||||
|
```
|
||||||
|
|
||||||
|
Python 实际上会先把多个返回值组合成一个元组,再把元组解包给多个变量。
|
||||||
|
|
||||||
|
也可以只用一个变量接收:
|
||||||
|
|
||||||
|
```python
|
||||||
|
summary = get_agent_summary({"name": "聊天助手", "tools": []})
|
||||||
|
print(summary)
|
||||||
|
print(type(summary))
|
||||||
|
```
|
||||||
|
|
||||||
|
此时 `summary` 是元组,例如 `("聊天助手", 0)`。
|
||||||
|
|
||||||
|
## 四、提前返回
|
||||||
|
|
||||||
|
`return` 不只负责返回结果,还会立即结束当前函数。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_agent_status(agent):
|
||||||
|
if not agent.get("enabled", False):
|
||||||
|
return "停用"
|
||||||
|
|
||||||
|
return "启用"
|
||||||
|
```
|
||||||
|
|
||||||
|
如果 Agent 没有启用,函数执行第一个 `return` 后就结束,不会继续执行下面的代码。
|
||||||
|
|
||||||
|
这种写法称为提前返回(Early Return)。它适合先处理无效数据或特殊情况,避免出现太多层缩进。
|
||||||
|
|
||||||
|
## 五、使用 `*args` 接收多个位置参数
|
||||||
|
|
||||||
|
有时无法提前确定调用者会传入几个位置参数,这时可以使用 `*args`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count_tools(*tools):
|
||||||
|
return len(tools)
|
||||||
|
|
||||||
|
|
||||||
|
print(count_tools("搜索"))
|
||||||
|
print(count_tools("搜索", "终端", "计算器"))
|
||||||
|
```
|
||||||
|
|
||||||
|
这里的 `args` 是 arguments 的缩写,表示“多个参数”。
|
||||||
|
|
||||||
|
需要注意:
|
||||||
|
|
||||||
|
- 参数名前面的 `*` 才是关键;
|
||||||
|
- `args` 是约定俗成的名称,也可以换成其他名称;
|
||||||
|
- 函数内部的 `tools` 是一个元组;
|
||||||
|
- 即使没有传入任何工具,`tools` 也是空元组。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def show_tools(*tools):
|
||||||
|
print(tools)
|
||||||
|
print(type(tools))
|
||||||
|
```
|
||||||
|
|
||||||
|
## 六、普通参数和 `*args` 一起使用
|
||||||
|
|
||||||
|
普通参数可以写在 `*args` 前面:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def build_tool_message(agent_name, *tools):
|
||||||
|
return f"{agent_name} 拥有 {len(tools)} 个工具"
|
||||||
|
|
||||||
|
|
||||||
|
message = build_tool_message("代码助手", "搜索", "终端")
|
||||||
|
print(message)
|
||||||
|
```
|
||||||
|
|
||||||
|
调用时,第一个位置参数交给 `agent_name`,剩余位置参数都被收集到 `tools` 元组中。
|
||||||
|
|
||||||
|
## 七、使用 `**kwargs` 接收多个关键字参数
|
||||||
|
|
||||||
|
如果无法提前确定调用者会传入哪些关键字参数,可以使用 `**kwargs`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def build_agent_config(**config):
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
agent_config = build_agent_config(
|
||||||
|
name="代码助手",
|
||||||
|
model="gpt-5",
|
||||||
|
enabled=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(agent_config)
|
||||||
|
```
|
||||||
|
|
||||||
|
`kwargs` 是 keyword arguments 的缩写,中文可理解为“多个关键字参数”。
|
||||||
|
|
||||||
|
函数内部的 `config` 是字典:
|
||||||
|
|
||||||
|
```python
|
||||||
|
{
|
||||||
|
"name": "代码助手",
|
||||||
|
"model": "gpt-5",
|
||||||
|
"enabled": True,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
同样,参数名前面的两个星号 `**` 才是关键,`kwargs` 只是常见命名。
|
||||||
|
|
||||||
|
## 八、普通参数和 `**kwargs` 一起使用
|
||||||
|
|
||||||
|
```python
|
||||||
|
def create_agent(name, **settings):
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"settings": settings,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
agent = create_agent("代码助手", model="gpt-5", enabled=True)
|
||||||
|
print(agent)
|
||||||
|
```
|
||||||
|
|
||||||
|
`name` 接收普通参数,其他关键字参数被收集到 `settings` 字典中。
|
||||||
|
|
||||||
|
## 九、调用函数时使用 `*` 解包列表或元组
|
||||||
|
|
||||||
|
星号也可以出现在函数调用中。此时它表示把列表或元组中的元素依次作为位置参数传入。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def add_three_numbers(first, second, third):
|
||||||
|
return first + second + third
|
||||||
|
|
||||||
|
|
||||||
|
numbers = [10, 20, 30]
|
||||||
|
total = add_three_numbers(*numbers)
|
||||||
|
print(total)
|
||||||
|
```
|
||||||
|
|
||||||
|
上面的调用相当于:
|
||||||
|
|
||||||
|
```python
|
||||||
|
total = add_three_numbers(10, 20, 30)
|
||||||
|
```
|
||||||
|
|
||||||
|
元素数量必须与函数所需的位置参数数量匹配,否则会产生 `TypeError`。
|
||||||
|
|
||||||
|
## 十、调用函数时使用 `**` 解包字典
|
||||||
|
|
||||||
|
两个星号可以把字典解包成关键字参数:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def describe_agent(name, model):
|
||||||
|
return f"{name} 使用 {model}"
|
||||||
|
|
||||||
|
|
||||||
|
agent_data = {
|
||||||
|
"name": "代码助手",
|
||||||
|
"model": "gpt-5",
|
||||||
|
}
|
||||||
|
|
||||||
|
description = describe_agent(**agent_data)
|
||||||
|
print(description)
|
||||||
|
```
|
||||||
|
|
||||||
|
上面的调用相当于:
|
||||||
|
|
||||||
|
```python
|
||||||
|
description = describe_agent(name="代码助手", model="gpt-5")
|
||||||
|
```
|
||||||
|
|
||||||
|
字典的键必须与函数参数名一致。
|
||||||
|
|
||||||
|
## 十一、如何选择参数形式
|
||||||
|
|
||||||
|
### 使用普通参数
|
||||||
|
|
||||||
|
参数数量固定、含义明确时,优先使用普通参数:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_total(first_number, second_number):
|
||||||
|
return first_number + second_number
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 `*args`
|
||||||
|
|
||||||
|
需要接收数量不固定的同类位置参数时使用:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count_tools(*tools):
|
||||||
|
return len(tools)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 `**kwargs`
|
||||||
|
|
||||||
|
需要接收数量或名称不固定的配置项时使用:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def build_config(**config):
|
||||||
|
return config
|
||||||
|
```
|
||||||
|
|
||||||
|
不要为了显得代码高级而强行使用 `*args` 或 `**kwargs`。参数固定时,普通参数通常更清楚。
|
||||||
|
|
||||||
|
## 十二、完整示例
|
||||||
|
|
||||||
|
本课示例文件为:
|
||||||
|
|
||||||
|
```text
|
||||||
|
01_python基础/1_13_函数进阶/advanced_functions.py
|
||||||
|
```
|
||||||
|
|
||||||
|
示例会依次演示:
|
||||||
|
|
||||||
|
1. 返回多个结果;
|
||||||
|
2. 提前返回;
|
||||||
|
3. 使用 `*args`;
|
||||||
|
4. 使用 `**kwargs`;
|
||||||
|
5. 解包列表和字典后调用函数。
|
||||||
|
|
||||||
|
## 十三、运行方法
|
||||||
|
|
||||||
|
在项目根目录执行:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python .\01_python基础\1_13_函数进阶\advanced_functions.py
|
||||||
|
```
|
||||||
|
|
||||||
|
运行练习:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python .\01_python基础\1_13_函数进阶\practice.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 十四、示例运行结果
|
||||||
|
|
||||||
|
```text
|
||||||
|
一、返回多个结果
|
||||||
|
Agent 名称:代码助手
|
||||||
|
工具数量:2
|
||||||
|
==============================
|
||||||
|
二、提前返回
|
||||||
|
启用
|
||||||
|
停用
|
||||||
|
==============================
|
||||||
|
三、任意数量的位置参数
|
||||||
|
工具数量:3
|
||||||
|
==============================
|
||||||
|
四、任意数量的关键字参数
|
||||||
|
{'name': '代码助手', 'model': 'gpt-5', 'enabled': True}
|
||||||
|
==============================
|
||||||
|
五、调用时解包数据
|
||||||
|
数字总和:60
|
||||||
|
代码助手 使用 gpt-5
|
||||||
|
```
|
||||||
|
|
||||||
|
字典的显示格式可能因环境而略有差异,但键和值应当一致。
|
||||||
|
|
||||||
|
## 十五、关键代码解析
|
||||||
|
|
||||||
|
```python
|
||||||
|
def count_tools(*tools):
|
||||||
|
return len(tools)
|
||||||
|
```
|
||||||
|
|
||||||
|
执行顺序如下:
|
||||||
|
|
||||||
|
1. 调用者传入零个或多个位置参数;
|
||||||
|
2. `*` 把这些参数收集到 `tools`;
|
||||||
|
3. `tools` 在函数内部是元组;
|
||||||
|
4. `len()` 统计元组中的元素数量;
|
||||||
|
5. `return` 把数量交给调用者。
|
||||||
|
|
||||||
|
```python
|
||||||
|
def build_agent_config(**config):
|
||||||
|
return config
|
||||||
|
```
|
||||||
|
|
||||||
|
执行顺序如下:
|
||||||
|
|
||||||
|
1. 调用者传入零个或多个关键字参数;
|
||||||
|
2. `**` 把参数名称和值收集到 `config`;
|
||||||
|
3. `config` 在函数内部是字典;
|
||||||
|
4. 函数把字典返回给调用者。
|
||||||
|
|
||||||
|
## 十六、常见错误
|
||||||
|
|
||||||
|
### 16.1 混淆 `*args` 和 `**kwargs`
|
||||||
|
|
||||||
|
- `*args` 收集位置参数,函数内部得到元组;
|
||||||
|
- `**kwargs` 收集关键字参数,函数内部得到字典。
|
||||||
|
|
||||||
|
### 16.2 忘记星号
|
||||||
|
|
||||||
|
`args` 和 `kwargs` 本身只是普通名称。真正产生收集效果的是 `*` 和 `**`。
|
||||||
|
|
||||||
|
### 16.3 解包后的参数数量不匹配
|
||||||
|
|
||||||
|
如果函数需要三个参数,列表却只有两个元素,会产生 `TypeError`,表示调用时提供的参数数量不正确。
|
||||||
|
|
||||||
|
### 16.4 字典键与参数名不一致
|
||||||
|
|
||||||
|
使用 `**dictionary` 调用函数时,字典键必须能对应函数参数名。
|
||||||
|
|
||||||
|
### 16.5 在 `return` 后继续编写必须执行的代码
|
||||||
|
|
||||||
|
函数执行到 `return` 就会结束,写在同一执行路径后面的代码不会运行。
|
||||||
|
|
||||||
|
### 16.6 所有函数都使用可变参数
|
||||||
|
|
||||||
|
固定且明确的数据应继续使用普通参数。过度使用可变参数会降低可读性。
|
||||||
|
|
||||||
|
## 十七、课堂练习
|
||||||
|
|
||||||
|
打开:
|
||||||
|
|
||||||
|
```text
|
||||||
|
01_python基础/1_13_函数进阶/practice.py
|
||||||
|
```
|
||||||
|
|
||||||
|
练习题已经明确提供输入数据、实现步骤、返回要求和预期结果。请先独立完成,再进行验证。
|
||||||
|
|
||||||
|
## 十八、本课小结
|
||||||
|
|
||||||
|
1. `return value1, value2` 可以返回多个结果;
|
||||||
|
2. 多个返回值实际会组合成元组;
|
||||||
|
3. 提前返回可以尽早结束函数;
|
||||||
|
4. `*args` 收集位置参数并形成元组;
|
||||||
|
5. `**kwargs` 收集关键字参数并形成字典;
|
||||||
|
6. 调用函数时,`*` 可以解包列表或元组;
|
||||||
|
7. 调用函数时,`**` 可以解包字典;
|
||||||
|
8. 参数固定时应优先使用普通参数。
|
||||||
|
|
||||||
|
## 十九、验收标准
|
||||||
|
|
||||||
|
- 能正确接收函数的多个返回值;
|
||||||
|
- 能解释 `return` 为什么会结束函数;
|
||||||
|
- 能使用 `*args` 接收不同数量的位置参数;
|
||||||
|
- 能说明 `*args` 在函数内部是元组;
|
||||||
|
- 能使用 `**kwargs` 接收关键字参数;
|
||||||
|
- 能说明 `**kwargs` 在函数内部是字典;
|
||||||
|
- 能使用 `*` 解包列表或元组后调用函数;
|
||||||
|
- 能使用 `**` 解包字典后调用函数;
|
||||||
|
- 示例程序和练习程序可以正常运行。
|
||||||
100
01_python基础/1_13_函数进阶/advanced_functions.py
Normal file
100
01_python基础/1_13_函数进阶/advanced_functions.py
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# 第 1-13 课示例:函数进阶
|
||||||
|
#
|
||||||
|
# 本文件依次演示:
|
||||||
|
# 1. 返回多个结果;
|
||||||
|
# 2. 提前返回;
|
||||||
|
# 3. 使用 *args 接收任意数量的位置参数;
|
||||||
|
# 4. 使用 **kwargs 接收任意数量的关键字参数;
|
||||||
|
# 5. 在调用函数时解包列表和字典。
|
||||||
|
|
||||||
|
|
||||||
|
def print_separator():
|
||||||
|
"""输出分隔线,让不同示例的结果更容易区分。"""
|
||||||
|
print("=" * 30)
|
||||||
|
|
||||||
|
|
||||||
|
def get_agent_summary(agent):
|
||||||
|
"""返回 Agent 名称和工具数量。"""
|
||||||
|
agent_name = agent["name"]
|
||||||
|
tool_count = len(agent.get("tools", []))
|
||||||
|
return agent_name, tool_count
|
||||||
|
|
||||||
|
|
||||||
|
def get_agent_status(agent):
|
||||||
|
"""根据 Agent 的 enabled 配置返回中文状态。"""
|
||||||
|
# get() 的第二个参数 False 是默认值。
|
||||||
|
# 如果字典中没有 enabled,就把它当作未启用处理。
|
||||||
|
if not agent.get("enabled", False):
|
||||||
|
return "停用"
|
||||||
|
|
||||||
|
# 前面的条件成立时,函数已经提前结束。
|
||||||
|
# 因此执行到这里时,可以确定 Agent 已经启用。
|
||||||
|
return "启用"
|
||||||
|
|
||||||
|
|
||||||
|
def count_tools(*tools):
|
||||||
|
"""返回调用者传入的工具数量。"""
|
||||||
|
# tools 在函数内部是元组,可以使用 len() 统计元素数量。
|
||||||
|
return len(tools)
|
||||||
|
|
||||||
|
|
||||||
|
def build_agent_config(**config):
|
||||||
|
"""把关键字参数收集成 Agent 配置字典并返回。"""
|
||||||
|
# config 在函数内部是字典。
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def add_three_numbers(first, second, third):
|
||||||
|
"""返回三个数字的和。"""
|
||||||
|
return first + second + third
|
||||||
|
|
||||||
|
|
||||||
|
def describe_agent(name, model):
|
||||||
|
"""返回包含 Agent 名称和模型的描述文本。"""
|
||||||
|
return f"{name} 使用 {model}"
|
||||||
|
|
||||||
|
|
||||||
|
print("一、返回多个结果")
|
||||||
|
example_agent = {
|
||||||
|
"name": "代码助手",
|
||||||
|
"tools": ["搜索", "终端"],
|
||||||
|
}
|
||||||
|
agent_name, tool_count = get_agent_summary(example_agent)
|
||||||
|
print(f"Agent 名称:{agent_name}")
|
||||||
|
print(f"工具数量:{tool_count}")
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
|
||||||
|
print("二、提前返回")
|
||||||
|
print(get_agent_status({"name": "代码助手", "enabled": True}))
|
||||||
|
print(get_agent_status({"name": "聊天助手", "enabled": False}))
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
|
||||||
|
print("三、任意数量的位置参数")
|
||||||
|
available_tool_count = count_tools("搜索", "终端", "计算器")
|
||||||
|
print(f"工具数量:{available_tool_count}")
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
|
||||||
|
print("四、任意数量的关键字参数")
|
||||||
|
agent_config = build_agent_config(
|
||||||
|
name="代码助手",
|
||||||
|
model="gpt-5",
|
||||||
|
enabled=True,
|
||||||
|
)
|
||||||
|
print(agent_config)
|
||||||
|
|
||||||
|
print_separator()
|
||||||
|
|
||||||
|
print("五、调用时解包数据")
|
||||||
|
numbers = [10, 20, 30]
|
||||||
|
total = add_three_numbers(*numbers)
|
||||||
|
print(f"数字总和:{total}")
|
||||||
|
|
||||||
|
agent_data = {
|
||||||
|
"name": "代码助手",
|
||||||
|
"model": "gpt-5",
|
||||||
|
}
|
||||||
|
description = describe_agent(**agent_data)
|
||||||
|
print(description)
|
||||||
119
01_python基础/1_13_函数进阶/practice.py
Normal file
119
01_python基础/1_13_函数进阶/practice.py
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# 第 1-13 课课堂练习:Agent 函数工具箱进阶
|
||||||
|
#
|
||||||
|
# 完成要求:
|
||||||
|
# 1. 按照每道题给出的函数名、参数、测试数据和预期结果完成代码。
|
||||||
|
# 2. 需要继续使用的结果必须通过 return 返回,再由调用者使用 print() 输出。
|
||||||
|
# 3. 使用有意义的英文蛇形函数名和变量名。
|
||||||
|
# 4. 函数体使用四个空格缩进。
|
||||||
|
# 5. 不要删除题目注释。
|
||||||
|
# 6. 完成后运行本文件,并逐项核对预期结果。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习一:定义一个返回多个结果的函数。
|
||||||
|
# 1. 定义 get_model_summary(models) 函数,参数 models 接收模型名称列表。
|
||||||
|
# 2. 函数使用 len(models) 得到模型数量。
|
||||||
|
# 3. 使用 models[0] 得到第一个模型名称。
|
||||||
|
# 4. 使用一个 return 同时返回“模型数量”和“第一个模型名称”。
|
||||||
|
# 5. 使用 ["gpt-5", "o3", "claude"] 调用函数,并用两个变量接收返回值。
|
||||||
|
# 6. 分别输出两个变量,预期输出:3 和 gpt-5。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习二:观察多个返回值的真实数据类型。
|
||||||
|
# 1. 再次调用练习一的 get_model_summary()。
|
||||||
|
# 2. 这次只使用一个变量 summary 接收全部返回值。
|
||||||
|
# 3. 输出 summary 和 type(summary)。
|
||||||
|
# 4. 预期 summary 为 (3, "gpt-5"),类型为 tuple。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习三:使用提前返回处理无效数据。
|
||||||
|
# 1. 定义 calculate_average(scores) 函数,scores 接收分数列表。
|
||||||
|
# 2. 如果 scores 是空列表,立即使用 return 返回 0。
|
||||||
|
# 3. 如果列表非空,返回 sum(scores) / len(scores)。
|
||||||
|
# sum() 用于计算列表中所有数字的总和。
|
||||||
|
# 4. 第一次使用 [80, 90, 100] 调用,保存并输出结果,预期为 90.0。
|
||||||
|
# 5. 第二次使用空列表 [] 调用,保存并输出结果,预期为 0。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习四:使用 *args 接收任意数量的工具。
|
||||||
|
# 1. 定义 count_agent_tools(*tools) 函数。
|
||||||
|
# 2. 函数内部使用 len(tools) 统计工具数量,并使用 return 返回。
|
||||||
|
# 3. 调用 count_agent_tools("搜索", "终端", "计算器"),保存并输出结果。
|
||||||
|
# 4. 再调用一次 count_agent_tools(),本次不传任何工具。
|
||||||
|
# 5. 两次预期输出分别为 3 和 0。
|
||||||
|
# 可参考 advanced_functions.py 中 count_tools(*tools) 的写法。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习五:确认 *args 在函数内部是元组。
|
||||||
|
# 1. 定义 collect_models(*models) 函数。
|
||||||
|
# 2. 函数直接使用 return 返回 models。
|
||||||
|
# 3. 传入 "gpt-5"、"o3" 和 "claude" 调用函数,把返回值保存到 collected_models。
|
||||||
|
# 4. 输出 collected_models 和它的类型。
|
||||||
|
# 5. 预期输出内容为 ("gpt-5", "o3", "claude"),类型为 tuple。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习六:组合普通参数和 *args。
|
||||||
|
# 1. 定义 build_agent_tool_message(agent_name, *tools) 函数。
|
||||||
|
# 2. 使用 return 返回:"{agent_name} 拥有 {len(tools)} 个工具"。
|
||||||
|
# 3. 使用 "代码助手"、"搜索"、"终端" 调用函数,保存并输出返回值。
|
||||||
|
# 4. 预期输出:代码助手 拥有 2 个工具。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习七:使用 **kwargs 收集关键字参数。
|
||||||
|
# 1. 定义 build_runtime_config(**settings) 函数。
|
||||||
|
# 2. 函数直接使用 return 返回 settings。
|
||||||
|
# 3. 使用以下三个关键字参数调用函数:
|
||||||
|
# model="gpt-5"、timeout=30、enabled=True。
|
||||||
|
# 4. 把返回值保存到 runtime_config,并输出它和它的类型。
|
||||||
|
# 5. 预期字典包含三个对应键值,类型为 dict。
|
||||||
|
# 可参考 advanced_functions.py 中 build_agent_config(**config) 的写法。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习八:组合普通参数和 **kwargs。
|
||||||
|
# 1. 定义 create_agent(name, **settings) 函数。
|
||||||
|
# 2. 函数返回一个字典,结构必须是:
|
||||||
|
# {"name": name, "settings": settings}
|
||||||
|
# 3. 使用 name="代码助手"、model="gpt-5"、enabled=True 调用函数。
|
||||||
|
# 4. 保存并输出返回值。
|
||||||
|
# 5. 预期结果中的 name 为“代码助手”,settings 是包含 model 和 enabled 的字典。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习九:使用 * 解包列表后调用函数。
|
||||||
|
# 1. 定义 multiply_three_numbers(first, second, third) 函数。
|
||||||
|
# 2. 函数使用 return 返回三个数字的乘积。
|
||||||
|
# 3. 创建列表 numbers = [2, 3, 4]。
|
||||||
|
# 4. 使用 multiply_three_numbers(*numbers) 调用函数,而不是手动写三个参数。
|
||||||
|
# 5. 保存并输出返回值,预期输出:24。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习十:使用 ** 解包字典后调用函数。
|
||||||
|
# 1. 定义 build_model_message(name, model) 函数。
|
||||||
|
# 2. 函数使用 return 返回:"{name} 使用模型 {model}"。
|
||||||
|
# 3. 创建字典:
|
||||||
|
# agent_data = {"name": "搜索助手", "model": "o3"}
|
||||||
|
# 4. 使用 build_model_message(**agent_data) 调用函数。
|
||||||
|
# 5. 保存并输出返回值,预期输出:搜索助手 使用模型 o3。
|
||||||
|
|
||||||
|
|
||||||
|
# 预期核心结果:
|
||||||
|
# 练习一分别得到 3 和 gpt-5;
|
||||||
|
# 练习二确认多个返回值组成 tuple;
|
||||||
|
# 非空分数列表的平均分为 90.0,空列表结果为 0;
|
||||||
|
# count_agent_tools() 分别返回 3 和 0;
|
||||||
|
# collect_models() 返回元组;
|
||||||
|
# Agent 工具消息显示 2 个工具;
|
||||||
|
# **kwargs 收集到的数据类型为 dict;
|
||||||
|
# create_agent() 返回包含 name 和 settings 的嵌套字典;
|
||||||
|
# 三个数字的乘积为 24;
|
||||||
|
# 字典解包后生成“搜索助手 使用模型 o3”。
|
||||||
|
|
||||||
|
|
||||||
|
# 完成后进行自查:
|
||||||
|
# 1. 多个返回值是否使用多个变量正确接收;
|
||||||
|
# 2. 只用一个变量接收多个返回值时,是否得到元组;
|
||||||
|
# 3. 空列表是否通过提前返回避免了除以零;
|
||||||
|
# 4. *args 在函数内部是否被当作元组使用;
|
||||||
|
# 5. **kwargs 在函数内部是否被当作字典使用;
|
||||||
|
# 6. 普通参数是否写在 *args 或 **kwargs 前面;
|
||||||
|
# 7. 调用时的 * 是否正确解包列表;
|
||||||
|
# 8. 调用时的 ** 是否正确解包字典;
|
||||||
|
# 9. 需要继续使用的计算结果是否通过 return 返回。
|
||||||
@@ -65,20 +65,3 @@
|
|||||||
# 3. 是否正确使用了 and 和 not;
|
# 3. 是否正确使用了 and 和 not;
|
||||||
# 4. += 是否更新了原变量;
|
# 4. += 是否更新了原变量;
|
||||||
# 5. 所有计算结果是否与手工推算一致。
|
# 5. 所有计算结果是否与手工推算一致。
|
||||||
|
|
||||||
# 计划学习总天数:30
|
|
||||||
# 已经完成的学习天数:7
|
|
||||||
# 每天计划学习的小时数:2.5
|
|
||||||
# 4
|
|
||||||
# ==============================
|
|
||||||
# 1. 计划总天数和已完成天数: 30,7
|
|
||||||
# 2. 剩余天数:23
|
|
||||||
# 3. 完整星期数和额外天数:4,2
|
|
||||||
# 4. 计划总学习小时数和已完成学习小时数:75.0,17.5
|
|
||||||
# has_started=True
|
|
||||||
# is_plan_finished=False
|
|
||||||
# has_remaining_days=True
|
|
||||||
# is_in_progress=True
|
|
||||||
# completed_tasks=4
|
|
||||||
#
|
|
||||||
# 进程已结束,退出代码为 0
|
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -189,11 +189,12 @@ Python/
|
|||||||
## 当前学习进度
|
## 当前学习进度
|
||||||
|
|
||||||
- 当前阶段:第一阶段——Python 基础语法。
|
- 当前阶段:第一阶段——Python 基础语法。
|
||||||
- 当前课程:`1_10_字典`。
|
- 当前课程:`1_13_函数进阶`。
|
||||||
- 当前状态:第十课学习中。
|
- 当前状态:第 1~13 课全部完成。
|
||||||
- 已完成课程:`1_1_hello_world` 至 `1_9_元组`。
|
- 已完成课程:`1_1_hello_world` 至 `1_13_函数进阶`。
|
||||||
- 已创建课程目录:`01_python基础/1_1_hello_world/` 至 `01_python基础/1_10_字典/`。
|
- 学习中的课程:暂无。
|
||||||
- 下一步:阅读第十课讲义、运行字典示例并完成课堂练习。
|
- 已创建课程目录:`01_python基础/1_1_hello_world/` 至 `01_python基础/1_13_函数进阶/`。
|
||||||
|
- 下一步:进行第一阶段知识复习,并准备 Python 基础综合项目。
|
||||||
|
|
||||||
## 建议环境
|
## 建议环境
|
||||||
|
|
||||||
@@ -208,11 +209,9 @@ Python/
|
|||||||
|
|
||||||
## 下一步
|
## 下一步
|
||||||
|
|
||||||
下一课将学习:
|
第 1~13 课已经完成。接下来将进行:
|
||||||
|
|
||||||
1. Python 是什么;
|
1. 回顾变量、条件判断、循环和常用数据结构;
|
||||||
2. 程序、编程语言和解释器分别是什么;
|
2. 回顾函数、参数和返回值;
|
||||||
3. 如何检查电脑是否已经安装 Python;
|
3. 完成 Python 基础阶段测试;
|
||||||
4. 如何安装并验证 Python;
|
4. 开始 Python 基础综合项目。
|
||||||
5. 如何创建和运行第一个 `hello_world.py` 程序;
|
|
||||||
6. 如何理解第一行 Python 代码。
|
|
||||||
|
|||||||
Reference in New Issue
Block a user