From b5023b8e25c0e360efcbd8103207762e8ff8d6ff Mon Sep 17 00:00:00 2001 From: "zhiye.sun" Date: Wed, 29 Jul 2026 16:31:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(python=E5=9F=BA=E7=A1=80):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AD=97=E5=85=B8=E6=95=99=E5=AD=A6=E8=AF=BE=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01_python基础/1_10_字典/README.md | 573 ++++++++++++++++++++++++ 01_python基础/1_10_字典/dictionaries.py | 118 +++++ 01_python基础/1_10_字典/practice.py | 105 +++++ README.md | 10 +- 4 files changed, 801 insertions(+), 5 deletions(-) create mode 100644 01_python基础/1_10_字典/README.md create mode 100644 01_python基础/1_10_字典/dictionaries.py create mode 100644 01_python基础/1_10_字典/practice.py diff --git a/01_python基础/1_10_字典/README.md b/01_python基础/1_10_字典/README.md new file mode 100644 index 0000000..c486a95 --- /dev/null +++ b/01_python基础/1_10_字典/README.md @@ -0,0 +1,573 @@ +# 第 1-10 课:字典 + +## 一、本课目标 + +完成本课后,你应该能够: + +1. 解释键值对是什么; +2. 创建字典和空字典; +3. 使用键读取字典中的值; +4. 使用 `get()` 安全读取数据; +5. 添加和修改键值对; +6. 使用 `pop()`、`del` 和 `clear()` 删除数据; +7. 使用 `keys()`、`values()` 和 `items()`; +8. 遍历字典的键、值和键值对; +9. 使用嵌套字典表达分组配置; +10. 使用列表保存多个字典记录; +11. 理解字典键的基本限制; +12. 判断列表、元组和字典的适用场景。 + +## 二、前置知识 + +开始本课前,你应该已经掌握: + +- 字符串、数字和布尔值; +- 列表与元组; +- `if` 条件判断; +- `for` 循环; +- `in` 成员判断; +- f-string 格式化输出。 + +## 三、为什么需要字典 + +上一课可以使用元组保存 Agent 配置: + +```python +agent_config = ("gpt-5", 0.7, 2000, True) +``` + +读取配置时依赖固定位置: + +```python +model_name = agent_config[0] +temperature = agent_config[1] +``` + +代码阅读者必须记住每个位置的含义。 + +字典(Dictionary,类型名为 `dict`)使用名称描述每一项数据: + +```python +agent_config = { + "model": "gpt-5", + "temperature": 0.7, + "max_tokens": 2000, + "enabled": True, +} +``` + +读取时直接使用字段名称: + +```python +print(agent_config["model"]) +print(agent_config["temperature"]) +``` + +这种代码更容易理解,也适合表达配置、用户、产品和接口数据。 + +## 四、键值对 + +字典中的每一项由键和值组成,称为键值对(Key-Value Pair): + +```python +"model": "gpt-5" +``` + +- 键(Key):`"model"`,用于定位数据; +- 值(Value):`"gpt-5"`,是真正保存的数据。 + +键和值之间使用英文冒号 `:`,多个键值对之间使用英文逗号分隔。 + +## 五、创建字典 + +### 5.1 创建包含数据的字典 + +```python +agent_config = { + "model": "gpt-5", + "temperature": 0.7, + "max_tokens": 2000, + "enabled": True, +} +``` + +多行字典的最后一个键值对后保留逗号,是常见的代码风格,便于以后增加字段和查看 Git 差异。 + +### 5.2 创建空字典 + +```python +empty_config = {} +``` + +也可以写成: + +```python +empty_config = dict() +``` + +初学阶段优先使用 `{}`。 + +### 5.3 查看类型与长度 + +```python +print(type(agent_config)) +print(len(agent_config)) +``` + +`len()` 返回键值对数量。 + +## 六、使用方括号读取值 + +```python +model_name = agent_config["model"] +``` + +方括号中写的是键,不是数字位置。 + +如果键不存在: + +```text +agent_config["timeout"] +``` + +会产生 `KeyError`,中文可以理解为“指定键不存在”。 + +适用场景:确定该键必须存在,缺少时应当暴露错误。 + +## 七、使用 `get()` 安全读取 + +```python +timeout = agent_config.get("timeout") +``` + +键不存在时,默认返回 `None`,不会产生 `KeyError`。 + +`None` 表示“没有值”或“空值”,它是 Python 中一个特殊对象,不是字符串 `"None"`。 + +可以设置默认值: + +```python +timeout = agent_config.get("timeout", 30) +``` + +如果 `timeout` 不存在,返回整数 `30`。 + +需要注意:`get()` 返回默认值不会自动把这个键写入字典。 + +## 八、判断键是否存在 + +`in` 用于判断字典中是否存在指定键: + +```python +if "model" in agent_config: + print(agent_config["model"]) +``` + +判断不存在: + +```python +if "timeout" not in agent_config: + print("尚未配置超时时间") +``` + +默认情况下,`in` 检查的是键,不是值: + +```python +print("model" in agent_config) # True +print("gpt-5" in agent_config) # False +``` + +## 九、添加和修改键值对 + +字典是可变对象,可以添加和修改数据。 + +### 9.1 添加新键 + +```python +agent_config["timeout"] = 30 +``` + +如果键原来不存在,就会新增。 + +### 9.2 修改已有键 + +```python +agent_config["temperature"] = 0.3 +``` + +如果键已经存在,就会覆盖旧值。 + +相同语法会根据键是否存在决定“新增”还是“修改”。 + +## 十、使用 `update()` 更新多个字段 + +```python +agent_config.update({ + "temperature": 0.2, + "timeout": 60, +}) +``` + +`update()` 会: + +- 修改已存在的键; +- 添加不存在的键。 + +它直接修改原字典,通常不返回更新后的字典。 + +## 十一、删除键值对 + +### 11.1 `pop()` 删除并返回值 + +```python +removed_timeout = agent_config.pop("timeout") +``` + +键不存在时会产生 `KeyError`。可以提供默认值: + +```python +removed_timeout = agent_config.pop("timeout", None) +``` + +这样键不存在时返回 `None`。 + +### 11.2 `del` 删除指定键 + +```python +if "timeout" in agent_config: + del agent_config["timeout"] +``` + +`del` 不返回被删除的值。 + +### 11.3 `clear()` 清空字典 + +```python +agent_config.clear() +``` + +字典变量仍然存在,但键值对数量变为 `0`。 + +## 十二、获取键、值和键值对 + +### 12.1 `keys()` + +```python +config_keys = agent_config.keys() +``` + +得到所有键。 + +### 12.2 `values()` + +```python +config_values = agent_config.values() +``` + +得到所有值。 + +### 12.3 `items()` + +```python +config_items = agent_config.items() +``` + +得到所有键值对。遍历字典时最常用。 + +这些方法返回的是字典视图(Dictionary View),不是普通列表。现阶段可以直接遍历;确实需要列表时,可以使用 `list()` 转换。 + +## 十三、遍历字典 + +### 13.1 遍历键 + +```python +for key in agent_config: + print(key) +``` + +也可以明确写成: + +```python +for key in agent_config.keys(): + print(key) +``` + +### 13.2 遍历值 + +```python +for value in agent_config.values(): + print(value) +``` + +### 13.3 同时遍历键和值 + +```python +for key, value in agent_config.items(): + print(f"{key}:{value}") +``` + +`items()` 每次提供一个包含键和值的二元素元组,再通过元组解包分别交给 `key` 和 `value`。 + +## 十四、字典是否有顺序 + +现代 Python 字典会保留键值对的插入顺序。 + +```python +config = { + "model": "gpt-5", + "temperature": 0.7, + "enabled": True, +} +``` + +遍历时通常按照写入顺序得到这些键。 + +但是字典的核心用途仍然是“通过键查找值”,不应依赖数字索引访问。字典不支持: + +```text +config[0] +``` + +除非数字 `0` 本身就是一个真实的键。 + +## 十五、字典键必须唯一 + +一个字典中不能同时存在两个相同的键: + +```python +config = { + "model": "gpt-5", + "model": "o3", +} +``` + +后面的值会覆盖前面的值,最终 `model` 是 `"o3"`。 + +因此,字典不能依靠重复键保存多条同名记录。 + +## 十六、什么数据可以作为键 + +字典键必须是可哈希(Hashable)的对象。初学阶段可以记住:常见不可变类型通常可以作为键。 + +常见可用键: + +- 字符串; +- 整数; +- 浮点数; +- 布尔值; +- 只包含不可变元素的元组。 + +列表不能作为键: + +```text +invalid_dict = {["Python", "FastAPI"]: "工具"} +``` + +会产生 `TypeError`,因为列表可变。 + +实际业务中最常用字符串键,含义清晰,也方便与 JSON 和接口数据对应。 + +## 十七、嵌套字典 + +字典的值可以是另一个字典: + +```python +agent_config = { + "model": { + "name": "gpt-5", + "temperature": 0.7, + }, + "runtime": { + "timeout": 30, + "enabled": True, + }, +} +``` + +读取嵌套值: + +```python +model_name = agent_config["model"]["name"] +timeout = agent_config["runtime"]["timeout"] +``` + +第一组方括号取得内部字典,第二组方括号从内部字典读取数据。 + +嵌套层级过深会降低可读性。真实项目应根据业务结构合理分组。 + +## 十八、列表中保存字典 + +如果要保存多个 Agent,可以使用列表存放多个字典: + +```python +agents = [ + {"name": "代码助手", "model": "gpt-5", "enabled": True}, + {"name": "搜索助手", "model": "o3", "enabled": False}, +] +``` + +遍历: + +```python +for agent in agents: + print(f"{agent['name']}:{agent['model']}") +``` + +可以理解为: + +- 列表负责保存多条记录; +- 每个字典负责描述一条记录的字段。 + +这种结构在接口返回的 JSON 数据中非常常见。 + +## 十九、字典中保存列表 + +字典的值也可以是列表: + +```python +agent = { + "name": "代码助手", + "tools": ["搜索", "计算", "写作"], +} +``` + +添加一个工具: + +```python +agent["tools"].append("代码执行") +``` + +这里先读取 `tools` 对应的列表,再调用列表的 `append()`。 + +## 二十、字典复制 + +直接赋值不会创建独立字典: + +```python +original_config = {"model": "gpt-5"} +alias_config = original_config +alias_config["model"] = "o3" +``` + +两个变量会看到同一个修改结果。 + +简单字典可以使用 `copy()`: + +```python +copied_config = original_config.copy() +copied_config["model"] = "o3" +``` + +这仍然是浅复制。字典内部如果包含列表或字典,内部对象仍可能共享。深复制属于进阶内容。 + +## 二十一、列表、元组和字典如何选择 + +### 列表 + +适合保存多个同类、有顺序、数量可能变化的数据: + +```python +tools = ["搜索", "计算", "写作"] +``` + +### 元组 + +适合保存固定结构、创建后不希望变化的数据: + +```python +position = (116.4, 39.9) +``` + +### 字典 + +适合保存带字段名称的数据: + +```python +agent = {"name": "代码助手", "model": "gpt-5"} +``` + +真实程序通常会组合使用三种结构。 + +## 二十二、运行本课示例 + +在 PowerShell 中执行: + +```powershell +cd D:\Code\Python\01_python基础\1_10_字典 +python dictionaries.py +``` + +示例无需用户输入,会展示字典的创建、读取、增删改查、遍历、嵌套和复制。 + +## 二十三、常见错误 + +### 23.1 使用不存在的键 + +确定键不一定存在时,可以使用 `get()` 或先使用 `in` 判断。 + +### 23.2 误以为 `in` 检查值 + +默认情况下,`in` 检查的是键。 + +### 23.3 字典键重复 + +相同键只能保留一个值,后面的值会覆盖前面的值。 + +### 23.4 使用列表作为键 + +列表可变,不能作为字典键。 + +### 23.5 遍历时直接修改字典大小 + +遍历字典期间直接添加或删除键,可能产生运行错误。需要修改结构时,可以先记录目标,循环结束后再修改。 + +### 23.6 直接赋值误认为复制 + +`backup = original` 不会创建独立字典。 + +## 二十四、课堂练习 + +打开 `practice.py`,完成“Agent 配置管理器”。 + +运行命令: + +```powershell +python practice.py +``` + +练习会要求你创建配置、读取默认值、修改字段、删除字段、遍历数据,并处理嵌套字典和 Agent 列表。 + +## 二十五、思考题 + +1. 字典与元组相比,读取配置时有什么优势? +2. 方括号读取与 `get()` 有什么区别? +3. `in` 默认判断字典的键还是值? +4. 为什么字典键必须唯一? +5. 为什么列表不能作为字典键? +6. `items()` 遍历时为什么可以使用两个变量? +7. 列表中保存字典适合表达什么数据? + +## 二十六、本课小结 + +- 字典使用键值对保存数据; +- 键用于定位数据,值是真正保存的内容; +- 方括号适合读取必须存在的键; +- `get()` 可以安全读取并提供默认值; +- 字典是可变对象,可以增删改键值对; +- `keys()`、`values()`、`items()` 提供不同遍历方式; +- 键必须唯一且可哈希; +- 字典可以嵌套,也可以与列表组合; +- 字段明确的数据通常适合使用字典。 + +## 二十七、验收标准 + +- [ ] 能创建字典和空字典; +- [ ] 能使用方括号和 `get()` 读取值; +- [ ] 能安全添加、修改和删除键值对; +- [ ] 能判断键是否存在; +- [ ] 能遍历键、值和键值对; +- [ ] 能使用嵌套字典; +- [ ] 能使用列表保存多个字典; +- [ ] 能解释常见字典键限制; +- [ ] 能完成并运行 `practice.py`; +- [ ] 能回答七道思考题。 diff --git a/01_python基础/1_10_字典/dictionaries.py b/01_python基础/1_10_字典/dictionaries.py new file mode 100644 index 0000000..21ff2ee --- /dev/null +++ b/01_python基础/1_10_字典/dictionaries.py @@ -0,0 +1,118 @@ +# 第 1-10 课示例:字典 +# +# 本文件使用 Agent 配置作为统一示例,演示字典的主要操作。 +# 示例无需用户输入,可以直接运行并对照注释观察结果。 + + +# 一、创建字典并读取字段 +agent_config = { + "model": "gpt-5", + "temperature": 0.7, + "max_tokens": 2000, + "enabled": True, +} + +print(f"完整配置:{agent_config}") +print(f"配置字段数量:{len(agent_config)}") +print(f"模型名称:{agent_config['model']}") + + +# 二、使用 get() 安全读取 +# timeout 不存在,因此返回指定的默认值 30。 +timeout = agent_config.get("timeout", 30) +print(f"超时时间:{timeout}") + + +# 三、添加和修改字段 +agent_config["timeout"] = 60 +agent_config["temperature"] = 0.3 +print(f"添加和修改后的配置:{agent_config}") + + +# 四、使用 update() 更新多个字段 +agent_config.update({ + "temperature": 0.2, + "retries": 3, +}) +print(f"批量更新后的配置:{agent_config}") + + +# 五、删除字段 +# pop() 返回被删除的值;提供默认值可以避免键不存在时报错。 +removed_retries = agent_config.pop("retries", None) +print(f"被删除的重试次数:{removed_retries}") + +if "timeout" in agent_config: + del agent_config["timeout"] + +print(f"删除后的配置:{agent_config}") + + +# 六、遍历键、值和键值对 +print("所有键:") +for key in agent_config.keys(): + print(key) + +print("所有值:") +for value in agent_config.values(): + print(value) + +print("所有键值对:") +for key, value in agent_config.items(): + print(f"{key}:{value}") + + +# 七、嵌套字典 +nested_config = { + "model": { + "name": "gpt-5", + "temperature": 0.7, + }, + "runtime": { + "timeout": 30, + "enabled": True, + }, +} + +print(f"嵌套模型名称:{nested_config['model']['name']}") +print(f"嵌套超时时间:{nested_config['runtime']['timeout']}") + + +# 八、列表中保存多个字典 +agents = [ + {"name": "代码助手", "model": "gpt-5", "enabled": True}, + {"name": "搜索助手", "model": "o3", "enabled": False}, +] + +for agent in agents: + # 使用已经学过的普通条件判断,把布尔值转换成更容易阅读的中文状态。 + if agent["enabled"]: + status_text = "启用" + else: + status_text = "停用" + + print(f"{agent['name']}:{agent['model']},状态:{status_text}") + + +# 九、字典中保存列表 +agent_profile = { + "name": "代码助手", + "tools": ["搜索", "计算"], +} +agent_profile["tools"].append("写作") +print(f"Agent 工具:{agent_profile['tools']}") + + +# 十、直接赋值与复制 +original_config = {"model": "gpt-5", "enabled": True} +alias_config = original_config +alias_config["model"] = "o3" + +print(f"直接赋值后的原字典:{original_config}") +print(f"直接赋值后的别名字典:{alias_config}") + +copied_config = original_config.copy() +copied_config["model"] = "gpt-5" + +print(f"复制后保持不变的原字典:{original_config}") +print(f"修改后的副本:{copied_config}") diff --git a/01_python基础/1_10_字典/practice.py b/01_python基础/1_10_字典/practice.py new file mode 100644 index 0000000..cb65c4f --- /dev/null +++ b/01_python基础/1_10_字典/practice.py @@ -0,0 +1,105 @@ +# 第 1-10 课课堂练习:Agent 配置管理器 +# +# 完成要求: +# 1. 根据注释完成字典的创建、读取、修改、删除、遍历和嵌套操作。 +# 2. 使用有意义的英文蛇形变量名。 +# 3. 读取可能不存在的键时使用 get() 或先使用 in 判断。 +# 4. 删除键前确认键存在,或为 pop() 提供默认值。 +# 5. 不要删除题目注释。 +# 6. 完成后运行本文件并核对预期结果。 + + +# 练习一:创建字典 agent_config,包含以下键值对: +# model:"gpt-5" +# temperature:0.7 +# max_tokens:2000 +# enabled:True + +# 练习二:输出以下信息: +# 1. 完整字典; +# 2. 键值对数量; +# 3. 使用方括号读取 model; +# 4. 使用 get() 读取 temperature。 + +# 练习三:使用 get() 读取不存在的 timeout,并提供默认值 30。 +# 将结果保存到 timeout,输出该变量。 +# 确认执行后 timeout 键仍未自动加入 agent_config。 + +# 练习四:完成以下添加和修改: +# 1. 添加 timeout,值为 60; +# 2. 把 temperature 修改为 0.3; +# 3. 使用 update() 添加 retries=3,并把 max_tokens 修改为 4000。 + +# 练习五:完成以下成员判断: +# 1. 判断是否存在 model 键,保存到 contains_model; +# 2. 判断是否存在 timeout 键,保存到 contains_timeout; +# 3. 判断 "gpt-5" 是否直接存在于字典键中,保存到 model_value_is_key。 +# 观察第三个结果,理解 in 默认检查键。 + +# 练习六:使用 pop() 删除 retries。 +# 将被删除的值保存到 removed_retries。 +# 为 pop() 提供默认值 None,避免键不存在时报错。 + +# 练习七:使用 in 判断 timeout 是否存在。 +# 如果存在,使用 del 删除 timeout。 + +# 练习八:分别完成三种遍历: +# 1. 遍历并输出所有键; +# 2. 遍历并输出所有值; +# 3. 使用 items() 同时遍历键和值,格式为“model:gpt-5”。 + +# 练习九:创建嵌套字典 nested_config: +# model 对应一个内部字典,包含 name="gpt-5"、temperature=0.7; +# runtime 对应一个内部字典,包含 timeout=30、enabled=True。 +# 输出嵌套的模型名称和超时时间。 + +# 练习十:创建 Agent 列表 agents,包含两个字典: +# 第一条:name="代码助手"、model="gpt-5"、enabled=True; +# 第二条:name="搜索助手"、model="o3"、enabled=False。 +# 使用 for 遍历并输出每个 Agent 的名称、模型和启用状态。 + +# 练习十一:创建字典 agent_profile: +# name="代码助手"; +# tools=["搜索", "计算"]。 +# 向 tools 列表追加 "写作",再输出工具列表。 + +# 练习十二:使用 copy() 创建 agent_config 的独立浅复制 backup_config。 +# 在 backup_config 中把 model 修改为 "o3"。 +# 分别输出两个字典,确认原字典的 model 仍为 "gpt-5"。 + +# 练习十三:使用 30 个等号输出分隔线,再输出最终报告: +# 1. agent_config; +# 2. timeout 的默认读取结果; +# 3. contains_model; +# 4. contains_timeout; +# 5. model_value_is_key; +# 6. removed_retries; +# 7. nested_config; +# 8. agents; +# 9. agent_profile; +# 10. backup_config。 + + +# 预期核心结果: +# 初次 get("timeout", 30) 得到 30,但不会自动新增键; +# 修改后的 temperature 为 0.3; +# 修改后的 max_tokens 为 4000; +# contains_model = True; +# 添加 timeout 后 contains_timeout = True; +# model_value_is_key = False; +# removed_retries = 3; +# timeout 最终被删除; +# 嵌套模型名称为 gpt-5,超时时间为 30; +# agent_profile 的 tools 包含“写作”; +# backup_config 的模型为 o3,但 agent_config 的模型仍为 gpt-5。 + + +# 完成后进行自查: +# 1. 方括号和 get() 是否按要求分别使用; +# 2. get() 默认值是否没有自动写入字典; +# 3. in 是否用于检查键; +# 4. 删除键时是否进行了安全处理; +# 5. items() 是否正确解包为 key 和 value; +# 6. 嵌套字典是否使用两层键读取; +# 7. 列表中的每个 Agent 是否使用字典表达; +# 8. 修改 backup_config 是否没有影响 agent_config。 diff --git a/README.md b/README.md index bf08526..8068f0e 100644 --- a/README.md +++ b/README.md @@ -189,11 +189,11 @@ Python/ ## 当前学习进度 - 当前阶段:第一阶段——Python 基础语法。 -- 当前课程:`1_9_元组`。 -- 当前状态:第九课学习中。 -- 已完成课程:`1_1_hello_world` 至 `1_8_列表`。 -- 已创建课程目录:`01_python基础/1_1_hello_world/` 至 `01_python基础/1_9_元组/`。 -- 下一步:阅读第九课讲义、运行元组示例并完成课堂练习。 +- 当前课程:`1_10_字典`。 +- 当前状态:第十课学习中。 +- 已完成课程:`1_1_hello_world` 至 `1_9_元组`。 +- 已创建课程目录:`01_python基础/1_1_hello_world/` 至 `01_python基础/1_10_字典/`。 +- 下一步:阅读第十课讲义、运行字典示例并完成课堂练习。 ## 建议环境