feat(python基础): 新增循环与字符串教学课程
This commit is contained in:
488
01_python基础/1_6_循环/README.md
Normal file
488
01_python基础/1_6_循环/README.md
Normal file
@@ -0,0 +1,488 @@
|
|||||||
|
# 第 1-6 课:循环
|
||||||
|
|
||||||
|
## 一、本课目标
|
||||||
|
|
||||||
|
完成本课后,你应该能够:
|
||||||
|
|
||||||
|
1. 解释循环为什么能减少重复代码;
|
||||||
|
2. 使用 `for` 循环按照指定次数重复执行代码;
|
||||||
|
3. 使用 `range()` 生成整数序列;
|
||||||
|
4. 使用 `while` 在条件成立期间重复执行;
|
||||||
|
5. 使用计数器记录执行次数;
|
||||||
|
6. 使用累加器汇总一组数据;
|
||||||
|
7. 在循环中结合 `if` 进行判断;
|
||||||
|
8. 使用 `break` 提前结束循环;
|
||||||
|
9. 使用 `continue` 跳过本次循环;
|
||||||
|
10. 识别并避免常见的死循环。
|
||||||
|
|
||||||
|
## 二、前置知识
|
||||||
|
|
||||||
|
开始本课前,你应该已经掌握:
|
||||||
|
|
||||||
|
- 变量与基础数据类型;
|
||||||
|
- 数字计算和比较运算;
|
||||||
|
- `if...elif...else` 条件判断;
|
||||||
|
- `input()` 和类型转换;
|
||||||
|
- 代码块需要使用四个空格缩进。
|
||||||
|
|
||||||
|
## 三、为什么需要循环
|
||||||
|
|
||||||
|
如果要输出五次学习提醒,可以重复写五行:
|
||||||
|
|
||||||
|
```python
|
||||||
|
print("开始学习 Python")
|
||||||
|
print("开始学习 Python")
|
||||||
|
print("开始学习 Python")
|
||||||
|
print("开始学习 Python")
|
||||||
|
print("开始学习 Python")
|
||||||
|
```
|
||||||
|
|
||||||
|
这种写法存在明显问题:
|
||||||
|
|
||||||
|
- 重复代码很多;
|
||||||
|
- 修改文字时要修改多个位置;
|
||||||
|
- 执行次数较大时无法手工编写;
|
||||||
|
- 容易漏写或写错。
|
||||||
|
|
||||||
|
循环(Loop)可以让一段代码重复执行:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for count in range(5):
|
||||||
|
print("开始学习 Python")
|
||||||
|
```
|
||||||
|
|
||||||
|
循环的核心思想是:让计算机负责重复,人只需要描述重复规则。
|
||||||
|
|
||||||
|
## 四、`for` 循环
|
||||||
|
|
||||||
|
`for` 循环适合处理“已经知道重复次数”或“依次处理一组数据”的场景。
|
||||||
|
|
||||||
|
基本结构:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for 循环变量 in 可迭代对象:
|
||||||
|
重复执行的代码
|
||||||
|
```
|
||||||
|
|
||||||
|
第一次接触“可迭代对象”时,可以先把它理解为能够依次提供数据的对象。字符串、列表和 `range()` 都可以依次提供数据。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for count in range(3):
|
||||||
|
print("正在进行 Agent 学习打卡")
|
||||||
|
```
|
||||||
|
|
||||||
|
输出三次相同内容。
|
||||||
|
|
||||||
|
每次循环时,`range(3)` 会依次提供一个整数,并临时保存到循环变量 `count` 中。
|
||||||
|
|
||||||
|
## 五、认识 `range()`
|
||||||
|
|
||||||
|
`range()` 用于表示一个整数范围,经常与 `for` 配合。
|
||||||
|
|
||||||
|
### 5.1 `range(结束值)`
|
||||||
|
|
||||||
|
```python
|
||||||
|
for number in range(5):
|
||||||
|
print(number)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
```
|
||||||
|
|
||||||
|
关键规则:从 `0` 开始,包含开始值,不包含结束值。
|
||||||
|
|
||||||
|
因此 `range(5)` 提供 5 个整数,但最后一个整数是 `4`。这种“不包含结束值”的规则在 Python 中非常常见。
|
||||||
|
|
||||||
|
### 5.2 `range(开始值, 结束值)`
|
||||||
|
|
||||||
|
```python
|
||||||
|
for day in range(1, 6):
|
||||||
|
print(day)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出 `1` 到 `5`。`6` 仍然不包含在范围中。
|
||||||
|
|
||||||
|
如果希望显示“第 1 次”到“第 5 次”,`range(1, 6)` 通常比 `range(5)` 更直观。
|
||||||
|
|
||||||
|
### 5.3 `range(开始值, 结束值, 步长)`
|
||||||
|
|
||||||
|
步长表示每次增加多少:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for number in range(0, 11, 2):
|
||||||
|
print(number)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
0
|
||||||
|
2
|
||||||
|
4
|
||||||
|
6
|
||||||
|
8
|
||||||
|
10
|
||||||
|
```
|
||||||
|
|
||||||
|
步长也可以是负数:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for number in range(5, 0, -1):
|
||||||
|
print(number)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出从 `5` 到 `1`,可用于倒计时。
|
||||||
|
|
||||||
|
## 六、使用循环变量
|
||||||
|
|
||||||
|
循环变量会在每次循环时保存当前数据:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for day in range(1, 4):
|
||||||
|
print(f"第 {day} 天:完成 Python 学习")
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
第 1 天:完成 Python 学习
|
||||||
|
第 2 天:完成 Python 学习
|
||||||
|
第 3 天:完成 Python 学习
|
||||||
|
```
|
||||||
|
|
||||||
|
循环变量应使用有意义的名称,例如 `day`、`task_number`,避免长期使用难以理解的 `a`、`x`。
|
||||||
|
|
||||||
|
## 七、遍历字符串
|
||||||
|
|
||||||
|
`for` 也能依次取得字符串中的每个字符:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for character in "Agent":
|
||||||
|
print(character)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
A
|
||||||
|
g
|
||||||
|
e
|
||||||
|
n
|
||||||
|
t
|
||||||
|
```
|
||||||
|
|
||||||
|
这种“从头到尾依次取出数据”的操作称为遍历(Traversal)。以后学习列表、字典和文件时,会经常使用遍历。
|
||||||
|
|
||||||
|
## 八、计数器
|
||||||
|
|
||||||
|
计数器(Counter)是用来记录次数的变量。
|
||||||
|
|
||||||
|
```python
|
||||||
|
completed_count = 0
|
||||||
|
|
||||||
|
for task_number in range(1, 6):
|
||||||
|
completed_count += 1
|
||||||
|
|
||||||
|
print(f"已完成 {completed_count} 个任务")
|
||||||
|
```
|
||||||
|
|
||||||
|
执行过程:
|
||||||
|
|
||||||
|
1. 循环前把计数器初始化为 `0`;
|
||||||
|
2. 每次循环执行 `completed_count += 1`;
|
||||||
|
3. 循环五次后,计数器变为 `5`。
|
||||||
|
|
||||||
|
初始化必须写在循环外。如果写在循环内,每次都会重新变回 `0`。
|
||||||
|
|
||||||
|
## 九、累加器
|
||||||
|
|
||||||
|
累加器(Accumulator)用于把多次产生的数值汇总起来。
|
||||||
|
|
||||||
|
```python
|
||||||
|
total_hours = 0.0
|
||||||
|
|
||||||
|
for day in range(1, 6):
|
||||||
|
daily_hours = float(input(f"请输入第 {day} 天的学习小时数:"))
|
||||||
|
total_hours += daily_hours
|
||||||
|
|
||||||
|
print(f"总学习时间:{total_hours} 小时")
|
||||||
|
```
|
||||||
|
|
||||||
|
`total_hours` 的变化过程可能是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
初始值:0.0
|
||||||
|
第 1 天后:2.0
|
||||||
|
第 2 天后:3.5
|
||||||
|
第 3 天后:6.0
|
||||||
|
```
|
||||||
|
|
||||||
|
计数器通常每次增加固定值;累加器通常加入每次得到的实际数据。
|
||||||
|
|
||||||
|
## 十、循环与条件判断结合
|
||||||
|
|
||||||
|
循环中可以使用 `if`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
passed_count = 0
|
||||||
|
|
||||||
|
for score in range(55, 101, 15):
|
||||||
|
if score >= 60:
|
||||||
|
passed_count += 1
|
||||||
|
print(f"{score} 分:通过")
|
||||||
|
else:
|
||||||
|
print(f"{score} 分:未通过")
|
||||||
|
|
||||||
|
print(f"通过数量:{passed_count}")
|
||||||
|
```
|
||||||
|
|
||||||
|
注意缩进层级:
|
||||||
|
|
||||||
|
- `for` 内部缩进一级;
|
||||||
|
- `if` 内部再缩进一级;
|
||||||
|
- 回到循环外时取消全部循环缩进。
|
||||||
|
|
||||||
|
## 十一、`while` 循环
|
||||||
|
|
||||||
|
`while` 的中文含义是“当……时”。只要条件为 `True`,循环就会继续。
|
||||||
|
|
||||||
|
基本结构:
|
||||||
|
|
||||||
|
```python
|
||||||
|
while 条件:
|
||||||
|
重复执行的代码
|
||||||
|
```
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```python
|
||||||
|
current_day = 1
|
||||||
|
|
||||||
|
while current_day <= 3:
|
||||||
|
print(f"完成第 {current_day} 天学习")
|
||||||
|
current_day += 1
|
||||||
|
```
|
||||||
|
|
||||||
|
执行过程:
|
||||||
|
|
||||||
|
1. `current_day` 初始为 `1`;
|
||||||
|
2. 判断 `current_day <= 3`,成立则执行循环;
|
||||||
|
3. 输出后把 `current_day` 增加 `1`;
|
||||||
|
4. 回到条件处重新判断;
|
||||||
|
5. 当 `current_day` 变为 `4` 时,条件为 `False`,循环结束。
|
||||||
|
|
||||||
|
## 十二、`for` 和 `while` 如何选择
|
||||||
|
|
||||||
|
通常可以这样判断:
|
||||||
|
|
||||||
|
- 已知需要重复多少次:优先考虑 `for`;
|
||||||
|
- 不知道次数,只知道结束条件:优先考虑 `while`。
|
||||||
|
|
||||||
|
示例场景:
|
||||||
|
|
||||||
|
```text
|
||||||
|
依次处理 7 天学习记录 → for
|
||||||
|
重复询问密码直到输入正确 → while
|
||||||
|
输出 1 到 100 → for
|
||||||
|
余额大于 0 时继续扣费 → while
|
||||||
|
```
|
||||||
|
|
||||||
|
两者有时可以互相改写,但应选择更能表达业务意图的方式。
|
||||||
|
|
||||||
|
## 十三、避免死循环
|
||||||
|
|
||||||
|
死循环(Infinite Loop)是无法自然结束的循环。
|
||||||
|
|
||||||
|
错误示例:
|
||||||
|
|
||||||
|
```text
|
||||||
|
current_day = 1
|
||||||
|
|
||||||
|
while current_day <= 3:
|
||||||
|
print(current_day)
|
||||||
|
```
|
||||||
|
|
||||||
|
循环中没有修改 `current_day`,条件会一直为 `True`,程序不断输出 `1`。
|
||||||
|
|
||||||
|
编写 `while` 时必须检查:
|
||||||
|
|
||||||
|
1. 条件中的变量是否会发生变化;
|
||||||
|
2. 变化方向是否会逐渐接近结束条件;
|
||||||
|
3. 是否存在明确的退出方式。
|
||||||
|
|
||||||
|
如果程序意外进入死循环,可以在终端中按 `Ctrl + C` 尝试停止。
|
||||||
|
|
||||||
|
## 十四、使用 `break` 提前结束循环
|
||||||
|
|
||||||
|
`break` 表示立即结束当前循环:
|
||||||
|
|
||||||
|
```python
|
||||||
|
while True:
|
||||||
|
command = input("请输入命令,输入 exit 结束:")
|
||||||
|
|
||||||
|
if command == "exit":
|
||||||
|
break
|
||||||
|
|
||||||
|
print(f"正在处理命令:{command}")
|
||||||
|
|
||||||
|
print("程序已结束")
|
||||||
|
```
|
||||||
|
|
||||||
|
`while True` 本身会无限循环,但遇到 `break` 后可以退出。只有存在清晰退出条件时,才应使用这种结构。
|
||||||
|
|
||||||
|
`break` 只结束它所在的最近一层循环,不会直接结束整个 Python 程序。
|
||||||
|
|
||||||
|
## 十五、使用 `continue` 跳过本次循环
|
||||||
|
|
||||||
|
`continue` 表示跳过本次循环剩余代码,直接开始下一次循环:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for day in range(1, 6):
|
||||||
|
if day == 3:
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"记录第 {day} 天学习数据")
|
||||||
|
```
|
||||||
|
|
||||||
|
第 3 天不会输出,其他天正常输出。
|
||||||
|
|
||||||
|
可以把两者简单区分为:
|
||||||
|
|
||||||
|
- `break`:整个循环到此结束;
|
||||||
|
- `continue`:只跳过当前这一次,循环还会继续。
|
||||||
|
|
||||||
|
## 十六、嵌套循环初步认识
|
||||||
|
|
||||||
|
循环内部还可以包含循环:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for week in range(1, 3):
|
||||||
|
for day in range(1, 4):
|
||||||
|
print(f"第 {week} 周,第 {day} 天")
|
||||||
|
```
|
||||||
|
|
||||||
|
外层循环每执行一次,内层循环都会完整执行三次,因此一共输出 `2 × 3 = 6` 行。
|
||||||
|
|
||||||
|
嵌套循环容易增加理解和运行成本。本课只要求看懂简单结构,练习不强制使用。
|
||||||
|
|
||||||
|
## 十七、运行本课示例
|
||||||
|
|
||||||
|
在 PowerShell 中执行:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd D:\Code\Python\01_python基础\1_6_循环
|
||||||
|
python loops.py
|
||||||
|
```
|
||||||
|
|
||||||
|
示例会演示:
|
||||||
|
|
||||||
|
- `range()` 的三种常见形式;
|
||||||
|
- 计数和累加;
|
||||||
|
- 循环结合条件判断;
|
||||||
|
- `while` 的变量更新;
|
||||||
|
- `break` 和 `continue`。
|
||||||
|
|
||||||
|
示例不需要用户输入,可以直接运行并对照注释观察结果。
|
||||||
|
|
||||||
|
## 十八、常见错误
|
||||||
|
|
||||||
|
### 18.1 忘记冒号
|
||||||
|
|
||||||
|
`for` 和 `while` 行末都必须使用英文冒号 `:`。
|
||||||
|
|
||||||
|
### 18.2 循环体没有缩进
|
||||||
|
|
||||||
|
属于循环的代码必须统一缩进四个空格。
|
||||||
|
|
||||||
|
### 18.3 `range()` 结束值理解错误
|
||||||
|
|
||||||
|
`range(1, 5)` 提供 `1、2、3、4`,不包含 `5`。
|
||||||
|
|
||||||
|
### 18.4 把计数器初始化写在循环内
|
||||||
|
|
||||||
|
这样每次循环都会重置,无法正确累计。
|
||||||
|
|
||||||
|
### 18.5 `while` 忘记更新条件变量
|
||||||
|
|
||||||
|
这很可能造成死循环。
|
||||||
|
|
||||||
|
### 18.6 混淆 `break` 与 `continue`
|
||||||
|
|
||||||
|
`break` 结束循环,`continue` 只跳过当前一次。
|
||||||
|
|
||||||
|
### 18.7 循环变量命名没有含义
|
||||||
|
|
||||||
|
优先使用 `day`、`task_number` 等名称,帮助读者理解当前遍历的数据。
|
||||||
|
|
||||||
|
## 十九、课堂练习
|
||||||
|
|
||||||
|
打开 `practice.py`,完成“Agent 学习打卡统计器”。程序需要收集连续多天的学习时长,统计总时长、有效学习天数和达标情况。
|
||||||
|
|
||||||
|
运行命令:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python practice.py
|
||||||
|
```
|
||||||
|
|
||||||
|
建议先使用以下数据测试:
|
||||||
|
|
||||||
|
```text
|
||||||
|
计划打卡天数:5
|
||||||
|
第 1 天:2
|
||||||
|
第 2 天:0
|
||||||
|
第 3 天:1.5
|
||||||
|
第 4 天:-1
|
||||||
|
第 5 天:3
|
||||||
|
```
|
||||||
|
|
||||||
|
约定:
|
||||||
|
|
||||||
|
- `-1` 表示本次数据无效,使用 `continue` 跳过;
|
||||||
|
- `0` 是有效记录,但不算完成学习;
|
||||||
|
- 大于 `0` 算一个有效学习日;
|
||||||
|
- 累计学习时长达到 `5` 小时视为总目标达标。
|
||||||
|
|
||||||
|
使用上述数据时,预期总时长为 `6.5` 小时,有效学习日为 `3` 天,无效记录为 `1` 条,总目标达标。
|
||||||
|
|
||||||
|
## 二十、思考题
|
||||||
|
|
||||||
|
1. `range(5)` 会提供哪些整数?
|
||||||
|
2. 为什么 `range(1, 6)` 可以表示第 1 到第 5 次?
|
||||||
|
3. 计数器与累加器有什么区别?
|
||||||
|
4. 哪些场景更适合使用 `while`?
|
||||||
|
5. `break` 和 `continue` 有什么区别?
|
||||||
|
6. `while` 循环为什么容易出现死循环?
|
||||||
|
7. 循环中的 `if` 为什么通常会比循环多一级缩进?
|
||||||
|
|
||||||
|
## 二十一、本课小结
|
||||||
|
|
||||||
|
- 循环用于重复执行代码;
|
||||||
|
- `for` 适合已知次数或依次处理数据的场景;
|
||||||
|
- `range()` 包含开始值,不包含结束值;
|
||||||
|
- 计数器记录次数,累加器汇总数值;
|
||||||
|
- `while` 在条件为真时持续执行;
|
||||||
|
- `while` 中必须确保条件最终能够变为假;
|
||||||
|
- `break` 提前结束循环;
|
||||||
|
- `continue` 跳过当前一次循环;
|
||||||
|
- 循环可以与条件判断结合,实现更真实的业务逻辑。
|
||||||
|
|
||||||
|
## 二十二、验收标准
|
||||||
|
|
||||||
|
- [ ] 能使用 `for` 和 `range()` 重复执行代码;
|
||||||
|
- [ ] 能解释 `range()` 为什么不包含结束值;
|
||||||
|
- [ ] 能使用计数器和累加器;
|
||||||
|
- [ ] 能在循环中使用条件判断;
|
||||||
|
- [ ] 能编写可以正常结束的 `while` 循环;
|
||||||
|
- [ ] 能区分 `break` 和 `continue`;
|
||||||
|
- [ ] 能完成并运行 `practice.py`;
|
||||||
|
- [ ] 能使用建议数据得到正确统计结果;
|
||||||
|
- [ ] 能回答七道思考题。
|
||||||
103
01_python基础/1_6_循环/loops.py
Normal file
103
01_python基础/1_6_循环/loops.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# 第 1-6 课示例:循环
|
||||||
|
#
|
||||||
|
# 本文件依次演示 for、range()、计数器、累加器、while、break 和 continue。
|
||||||
|
# 每段示例都会直接运行,不要求用户输入,便于重复观察结果。
|
||||||
|
|
||||||
|
|
||||||
|
# 一、使用 range(结束值)
|
||||||
|
# range(3) 依次提供 0、1、2,不包含结束值 3。
|
||||||
|
for number in range(3):
|
||||||
|
print(f"range(3) 当前数字:{number}")
|
||||||
|
|
||||||
|
|
||||||
|
# 二、指定开始值和结束值
|
||||||
|
# range(1, 4) 依次提供 1、2、3,适合显示自然的次数编号。
|
||||||
|
for day in range(1, 4):
|
||||||
|
print(f"第 {day} 天:完成 Python 学习")
|
||||||
|
|
||||||
|
|
||||||
|
# 三、指定步长
|
||||||
|
# 从 0 开始,每次增加 2,在到达 11 前结束。
|
||||||
|
for even_number in range(0, 11, 2):
|
||||||
|
print(f"当前偶数:{even_number}")
|
||||||
|
|
||||||
|
|
||||||
|
# 四、遍历字符串
|
||||||
|
# for 会依次取得字符串中的每一个字符。
|
||||||
|
for character in "Agent":
|
||||||
|
print(f"当前字符:{character}")
|
||||||
|
|
||||||
|
|
||||||
|
# 五、使用计数器
|
||||||
|
# 计数器必须在循环外初始化,否则每次循环都会重新变为 0。
|
||||||
|
completed_count = 0
|
||||||
|
|
||||||
|
for task_number in range(1, 6):
|
||||||
|
completed_count += 1
|
||||||
|
print(f"完成第 {task_number} 个任务")
|
||||||
|
|
||||||
|
print(f"任务完成总数:{completed_count}")
|
||||||
|
|
||||||
|
|
||||||
|
# 六、使用累加器
|
||||||
|
# daily_hours 表示五天的学习时长。
|
||||||
|
# 列表会在后续课程详细讲解,本例只需知道 for 能依次取得其中的数字。
|
||||||
|
daily_hours = [2.0, 1.5, 0.0, 2.5, 3.0]
|
||||||
|
total_hours = 0.0
|
||||||
|
|
||||||
|
for hours in daily_hours:
|
||||||
|
total_hours += hours
|
||||||
|
|
||||||
|
print(f"五天总学习时长:{total_hours} 小时")
|
||||||
|
|
||||||
|
|
||||||
|
# 七、循环结合条件判断
|
||||||
|
# 只有学习时长大于 0 的记录才算有效学习日。
|
||||||
|
effective_days = 0
|
||||||
|
|
||||||
|
for hours in daily_hours:
|
||||||
|
if hours > 0:
|
||||||
|
effective_days += 1
|
||||||
|
|
||||||
|
print(f"有效学习日:{effective_days} 天")
|
||||||
|
|
||||||
|
|
||||||
|
# 八、while 循环
|
||||||
|
# 每次循环末尾增加 current_day,确保条件最终会变为 False。
|
||||||
|
current_day = 1
|
||||||
|
|
||||||
|
while current_day <= 3:
|
||||||
|
print(f"while 正在处理第 {current_day} 天")
|
||||||
|
current_day += 1
|
||||||
|
|
||||||
|
|
||||||
|
# 九、使用 continue 跳过无效数据
|
||||||
|
# -1 表示无效记录;遇到它时跳过本次循环的剩余代码。
|
||||||
|
learning_records = [2.0, -1.0, 1.5, 0.0]
|
||||||
|
valid_total_hours = 0.0
|
||||||
|
|
||||||
|
for hours in learning_records:
|
||||||
|
if hours == -1:
|
||||||
|
print("发现无效记录,本次跳过")
|
||||||
|
continue
|
||||||
|
|
||||||
|
valid_total_hours += hours
|
||||||
|
|
||||||
|
print(f"排除无效记录后的总时长:{valid_total_hours} 小时")
|
||||||
|
|
||||||
|
|
||||||
|
# 十、使用 break 提前结束循环
|
||||||
|
# 当 task_number 等于 4 时结束循环,因此不会处理第 4、5 个任务。
|
||||||
|
for task_number in range(1, 6):
|
||||||
|
if task_number == 4:
|
||||||
|
print("收到停止信号,提前结束任务循环")
|
||||||
|
break
|
||||||
|
|
||||||
|
print(f"正在处理第 {task_number} 个任务")
|
||||||
|
|
||||||
|
|
||||||
|
# 十一、简单嵌套循环
|
||||||
|
# 外层循环执行两次;每次都会让内层循环完整执行三次。
|
||||||
|
for week in range(1, 3):
|
||||||
|
for day in range(1, 4):
|
||||||
|
print(f"第 {week} 周,第 {day} 天")
|
||||||
96
01_python基础/1_6_循环/practice.py
Normal file
96
01_python基础/1_6_循环/practice.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# 第 1-6 课课堂练习:Agent 学习打卡统计器
|
||||||
|
#
|
||||||
|
# 完成要求:
|
||||||
|
# 1. 根据注释使用 for、range()、if、continue、计数器和累加器。
|
||||||
|
# 2. 输入内容需要转换为正确的数字类型。
|
||||||
|
# 3. 使用有意义的英文蛇形变量名。
|
||||||
|
# 4. 注意冒号和四个空格缩进。
|
||||||
|
# 5. 不要删除题目注释。
|
||||||
|
# 6. 完成后使用题目提供的数据检查结果。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习一:接收计划打卡天数。
|
||||||
|
# 使用 int() 转换,并保存到 planned_days。
|
||||||
|
|
||||||
|
# 练习二:在循环开始前创建三个统计变量:
|
||||||
|
# 1. total_hours:总学习时长,初始值为 0.0;
|
||||||
|
# 2. effective_days:有效学习日数量,初始值为 0;
|
||||||
|
# 3. invalid_records:无效记录数量,初始值为 0。
|
||||||
|
|
||||||
|
# 练习三:使用 for 和 range() 循环 planned_days 次。
|
||||||
|
# 建议让循环变量 day 从 1 开始,这样提示语可以直接显示“第几天”。
|
||||||
|
# 注意:range() 的结束值不包含在结果中,需要自行计算正确结束值。
|
||||||
|
|
||||||
|
# 练习四:在循环中接收当天学习小时数。
|
||||||
|
# 提示语应包含当前 day,例如“请输入第 1 天的学习小时数”。
|
||||||
|
# 使用 float() 转换,并保存到 daily_hours。
|
||||||
|
|
||||||
|
# 练习五:在循环中判断 daily_hours 是否等于 -1。
|
||||||
|
# 如果等于 -1:
|
||||||
|
# 1. invalid_records 增加 1;
|
||||||
|
# 2. 输出“本条记录无效,已跳过”;
|
||||||
|
# 3. 使用 continue 跳过本次循环剩余代码。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习六:对于没有被 continue 跳过的有效记录:
|
||||||
|
# 1. 把 daily_hours 累加到 total_hours;
|
||||||
|
# 2. 如果 daily_hours 大于 0,让 effective_days 增加 1;
|
||||||
|
# 3. 如果 daily_hours 等于 0,输出“今天没有完成学习”。
|
||||||
|
|
||||||
|
# 练习七:循环结束后,判断总目标是否达标。
|
||||||
|
# total_hours 大于或等于 5 时,target_reached 为 True,否则为 False。
|
||||||
|
# 请直接使用比较运算生成布尔值,不必使用 if 分别赋值。
|
||||||
|
|
||||||
|
# 练习八:使用字符串乘法输出 30 个等号,再使用 f-string 输出统计报告:
|
||||||
|
# 1. 计划打卡天数 planned_days;
|
||||||
|
# 2. 总学习时长 total_hours;
|
||||||
|
# 3. 有效学习日 effective_days;
|
||||||
|
# 4. 无效记录 invalid_records;
|
||||||
|
# 5. 总目标是否达标 target_reached。
|
||||||
|
|
||||||
|
# 练习九:使用 if...else 输出最终建议:
|
||||||
|
# - target_reached 为 True:输出“学习总时长已达标,请保持节奏。”
|
||||||
|
# - target_reached 为 False:输出“学习总时长尚未达标,请继续努力。”
|
||||||
|
|
||||||
|
# 练习十:额外完成一个独立的 while 循环。
|
||||||
|
# 1. 创建 review_count,初始值为 1;
|
||||||
|
# 2. 当 review_count 小于或等于 3 时,输出“正在进行第几次复习”;
|
||||||
|
# 3. 每次循环末尾让 review_count 增加 1;
|
||||||
|
# 4. 确保循环能够正常结束。
|
||||||
|
|
||||||
|
# 第一次运行请使用以下数据:
|
||||||
|
# 计划打卡天数:5
|
||||||
|
# 第 1 天:2
|
||||||
|
# 第 2 天:0
|
||||||
|
# 第 3 天:1.5
|
||||||
|
# 第 4 天:-1
|
||||||
|
# 第 5 天:3
|
||||||
|
#
|
||||||
|
# 预期结果:
|
||||||
|
# total_hours = 6.5
|
||||||
|
# effective_days = 3
|
||||||
|
# invalid_records = 1
|
||||||
|
# target_reached = True
|
||||||
|
# while 循环依次输出第 1、2、3 次复习,然后正常结束。
|
||||||
|
|
||||||
|
|
||||||
|
# 第二次运行可以测试未达标情况:
|
||||||
|
# 计划打卡天数:3
|
||||||
|
# 第 1 天:1
|
||||||
|
# 第 2 天:0
|
||||||
|
# 第 3 天:2
|
||||||
|
#
|
||||||
|
# 预期结果:
|
||||||
|
# total_hours = 3.0
|
||||||
|
# effective_days = 2
|
||||||
|
# invalid_records = 0
|
||||||
|
# target_reached = False
|
||||||
|
|
||||||
|
|
||||||
|
# 完成后进行自查:
|
||||||
|
# 1. for 循环是否正好执行 planned_days 次;
|
||||||
|
# 2. -1 是否只增加无效记录,没有加入总时长;
|
||||||
|
# 3. 0 是否加入总时长,但没有增加有效学习日;
|
||||||
|
# 4. continue 是否位于无效数据分支中;
|
||||||
|
# 5. 统计变量是否都在循环外初始化;
|
||||||
|
# 6. while 循环是否能够在三次后正常结束。
|
||||||
637
01_python基础/1_7_字符串/README.md
Normal file
637
01_python基础/1_7_字符串/README.md
Normal file
@@ -0,0 +1,637 @@
|
|||||||
|
# 第 1-7 课:字符串
|
||||||
|
|
||||||
|
## 一、本课目标
|
||||||
|
|
||||||
|
完成本课后,你应该能够:
|
||||||
|
|
||||||
|
1. 解释字符串是什么;
|
||||||
|
2. 使用索引读取字符串中的单个字符;
|
||||||
|
3. 使用切片取得字符串的一部分;
|
||||||
|
4. 使用 `len()` 获取字符串长度;
|
||||||
|
5. 使用 `for` 遍历字符串;
|
||||||
|
6. 使用常见字符串方法清理、转换和查找文本;
|
||||||
|
7. 使用 `in` 判断字符串是否包含指定内容;
|
||||||
|
8. 使用 `split()` 分割字符串,使用 `join()` 连接文本;
|
||||||
|
9. 理解字符串不可变的含义;
|
||||||
|
10. 编写一个简单的 Agent 提示词文本分析器。
|
||||||
|
|
||||||
|
## 二、前置知识
|
||||||
|
|
||||||
|
开始本课前,你应该已经掌握:
|
||||||
|
|
||||||
|
- 创建字符串变量;
|
||||||
|
- 使用 `input()` 接收字符串;
|
||||||
|
- 使用 f-string 输出变量;
|
||||||
|
- 使用条件判断;
|
||||||
|
- 使用 `for` 循环遍历数据。
|
||||||
|
|
||||||
|
## 三、字符串是什么
|
||||||
|
|
||||||
|
字符串(String,类型名为 `str`)是一串按照顺序排列的字符。
|
||||||
|
|
||||||
|
```python
|
||||||
|
prompt = "请帮我分析这段代码"
|
||||||
|
```
|
||||||
|
|
||||||
|
这个字符串包含中文字符。字符串也可以包含:
|
||||||
|
|
||||||
|
- 英文字母;
|
||||||
|
- 数字字符;
|
||||||
|
- 空格;
|
||||||
|
- 标点符号;
|
||||||
|
- 换行符等特殊字符。
|
||||||
|
|
||||||
|
只要内容被成对的单引号或双引号包围,Python 就会把它看作字符串:
|
||||||
|
|
||||||
|
```python
|
||||||
|
name = "Bruce"
|
||||||
|
age_text = "18"
|
||||||
|
empty_text = ""
|
||||||
|
```
|
||||||
|
|
||||||
|
`age_text` 看起来像数字,但它的数据类型仍然是字符串。
|
||||||
|
|
||||||
|
## 四、字符串中的字符有位置
|
||||||
|
|
||||||
|
字符串中的每个字符都有编号,这个编号称为索引(Index)。
|
||||||
|
|
||||||
|
Python 的索引从 `0` 开始:
|
||||||
|
|
||||||
|
```text
|
||||||
|
字符串: A g e n t
|
||||||
|
正索引: 0 1 2 3 4
|
||||||
|
负索引:-5 -4 -3 -2 -1
|
||||||
|
```
|
||||||
|
|
||||||
|
读取单个字符:
|
||||||
|
|
||||||
|
```python
|
||||||
|
word = "Agent"
|
||||||
|
|
||||||
|
print(word[0]) # A
|
||||||
|
print(word[1]) # g
|
||||||
|
print(word[-1]) # t
|
||||||
|
```
|
||||||
|
|
||||||
|
方括号 `[]` 用于指定索引。
|
||||||
|
|
||||||
|
### 4.1 负索引
|
||||||
|
|
||||||
|
负索引从字符串末尾开始:
|
||||||
|
|
||||||
|
- `-1` 表示最后一个字符;
|
||||||
|
- `-2` 表示倒数第二个字符;
|
||||||
|
- 依此类推。
|
||||||
|
|
||||||
|
需要取得最后一个字符时,`word[-1]` 比先计算字符串长度更方便。
|
||||||
|
|
||||||
|
### 4.2 索引越界
|
||||||
|
|
||||||
|
`"Agent"` 只有 5 个字符,有效正索引是 `0` 到 `4`。
|
||||||
|
|
||||||
|
```text
|
||||||
|
word[5]
|
||||||
|
```
|
||||||
|
|
||||||
|
会产生 `IndexError`,中文可以理解为“索引超出有效范围”。
|
||||||
|
|
||||||
|
## 五、使用 `len()` 获取长度
|
||||||
|
|
||||||
|
`len()` 返回字符串包含的字符数量:
|
||||||
|
|
||||||
|
```python
|
||||||
|
prompt = "Hello"
|
||||||
|
prompt_length = len(prompt)
|
||||||
|
|
||||||
|
print(prompt_length)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出为 `5`。
|
||||||
|
|
||||||
|
空格和标点也会占用字符位置:
|
||||||
|
|
||||||
|
```python
|
||||||
|
print(len("A B")) # 结果为 3
|
||||||
|
```
|
||||||
|
|
||||||
|
`len()` 常用于:
|
||||||
|
|
||||||
|
- 检查用户输入是否过短或过长;
|
||||||
|
- 统计提示词长度;
|
||||||
|
- 判断字符串是否为空;
|
||||||
|
- 配合索引和循环处理文本。
|
||||||
|
|
||||||
|
## 六、字符串切片
|
||||||
|
|
||||||
|
切片(Slicing)用于取得字符串的一部分。
|
||||||
|
|
||||||
|
基本形式:
|
||||||
|
|
||||||
|
```python
|
||||||
|
字符串[开始索引:结束索引]
|
||||||
|
```
|
||||||
|
|
||||||
|
切片包含开始索引,不包含结束索引:
|
||||||
|
|
||||||
|
```python
|
||||||
|
word = "Python"
|
||||||
|
|
||||||
|
print(word[0:3]) # Pyt
|
||||||
|
print(word[2:6]) # thon
|
||||||
|
```
|
||||||
|
|
||||||
|
这种规则与 `range()` 相似:包含开始,不包含结束。
|
||||||
|
|
||||||
|
### 6.1 省略开始或结束索引
|
||||||
|
|
||||||
|
```python
|
||||||
|
word = "Python"
|
||||||
|
|
||||||
|
print(word[:3]) # 从开头到索引 3 之前:Pyt
|
||||||
|
print(word[3:]) # 从索引 3 到末尾:hon
|
||||||
|
print(word[:]) # 整个字符串:Python
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 使用负索引切片
|
||||||
|
|
||||||
|
```python
|
||||||
|
file_name = "report.txt"
|
||||||
|
|
||||||
|
print(file_name[-3:]) # txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 指定步长
|
||||||
|
|
||||||
|
完整形式:
|
||||||
|
|
||||||
|
```python
|
||||||
|
字符串[开始索引:结束索引:步长]
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
word = "Python"
|
||||||
|
|
||||||
|
print(word[::2]) # Pto
|
||||||
|
print(word[::-1]) # nohtyP
|
||||||
|
```
|
||||||
|
|
||||||
|
`[::-1]` 常用于反转字符串。现阶段理解其结果即可,不需要死记复杂切片组合。
|
||||||
|
|
||||||
|
### 6.4 切片通常不会越界报错
|
||||||
|
|
||||||
|
```python
|
||||||
|
word = "Agent"
|
||||||
|
print(word[0:100])
|
||||||
|
```
|
||||||
|
|
||||||
|
结果仍然是 `Agent`。单个索引越界通常报错,而切片结束位置超过长度时会安全地取到末尾。
|
||||||
|
|
||||||
|
## 七、遍历字符串
|
||||||
|
|
||||||
|
字符串可以使用 `for` 逐个处理字符:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for character in "Agent":
|
||||||
|
print(character)
|
||||||
|
```
|
||||||
|
|
||||||
|
统计字母出现次数:
|
||||||
|
|
||||||
|
```python
|
||||||
|
letter_count = 0
|
||||||
|
|
||||||
|
for character in "Agent application":
|
||||||
|
if character == "a":
|
||||||
|
letter_count += 1
|
||||||
|
|
||||||
|
print(letter_count)
|
||||||
|
```
|
||||||
|
|
||||||
|
需要注意英文大小写。`"A"` 和 `"a"` 是不同字符。
|
||||||
|
|
||||||
|
## 八、字符串方法是什么
|
||||||
|
|
||||||
|
方法(Method)是某种数据自身提供的操作。
|
||||||
|
|
||||||
|
字符串方法通常写成:
|
||||||
|
|
||||||
|
```python
|
||||||
|
字符串.方法名()
|
||||||
|
```
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
```python
|
||||||
|
user_input = " Python "
|
||||||
|
clean_text = user_input.strip()
|
||||||
|
```
|
||||||
|
|
||||||
|
点号 `.` 表示使用这个字符串提供的 `strip()` 方法。
|
||||||
|
|
||||||
|
方法与面向对象有关,将在后续阶段系统学习。本课先掌握常用字符串方法的用途。
|
||||||
|
|
||||||
|
## 九、清理字符串
|
||||||
|
|
||||||
|
### 9.1 `strip()`
|
||||||
|
|
||||||
|
`strip()` 删除字符串开头和结尾的空白:
|
||||||
|
|
||||||
|
```python
|
||||||
|
raw_text = " Python Agent "
|
||||||
|
clean_text = raw_text.strip()
|
||||||
|
|
||||||
|
print(clean_text)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Python Agent
|
||||||
|
```
|
||||||
|
|
||||||
|
它不会删除字符串中间的正常空格。
|
||||||
|
|
||||||
|
### 9.2 `lstrip()` 与 `rstrip()`
|
||||||
|
|
||||||
|
- `lstrip()`:只清理左侧;
|
||||||
|
- `rstrip()`:只清理右侧。
|
||||||
|
|
||||||
|
处理用户输入时,`strip()` 最常用。
|
||||||
|
|
||||||
|
## 十、转换英文字母大小写
|
||||||
|
|
||||||
|
```python
|
||||||
|
technology = "FastAPI"
|
||||||
|
|
||||||
|
print(technology.lower()) # fastapi
|
||||||
|
print(technology.upper()) # FASTAPI
|
||||||
|
```
|
||||||
|
|
||||||
|
常见方法:
|
||||||
|
|
||||||
|
- `lower()`:转成小写;
|
||||||
|
- `upper()`:转成大写;
|
||||||
|
- `title()`:让英文单词首字母大写;
|
||||||
|
- `capitalize()`:让字符串首字符大写,其余英文字符转为小写。
|
||||||
|
|
||||||
|
大小写转换常用于不区分大小写的输入判断:
|
||||||
|
|
||||||
|
```python
|
||||||
|
answer = input("是否继续(yes/no):").strip().lower()
|
||||||
|
|
||||||
|
if answer == "yes":
|
||||||
|
print("继续执行")
|
||||||
|
```
|
||||||
|
|
||||||
|
这样输入 `YES`、`Yes` 或两侧带空格时也能正确识别。
|
||||||
|
|
||||||
|
## 十一、替换文本
|
||||||
|
|
||||||
|
`replace()` 返回替换后的新字符串:
|
||||||
|
|
||||||
|
```python
|
||||||
|
old_text = "我正在学习 Java"
|
||||||
|
new_text = old_text.replace("Java", "Python")
|
||||||
|
|
||||||
|
print(new_text)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
我正在学习 Python
|
||||||
|
```
|
||||||
|
|
||||||
|
原始变量 `old_text` 不会自动改变。
|
||||||
|
|
||||||
|
## 十二、查找和统计
|
||||||
|
|
||||||
|
### 12.1 使用 `in`
|
||||||
|
|
||||||
|
`in` 判断某段内容是否包含在字符串中,结果是布尔值:
|
||||||
|
|
||||||
|
```python
|
||||||
|
prompt = "请使用 Python 编写 Agent"
|
||||||
|
|
||||||
|
contains_python = "Python" in prompt
|
||||||
|
print(contains_python)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 12.2 `find()`
|
||||||
|
|
||||||
|
`find()` 返回第一次出现的位置:
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = "Python Agent"
|
||||||
|
|
||||||
|
print(text.find("Agent")) # 7
|
||||||
|
print(text.find("Java")) # -1
|
||||||
|
```
|
||||||
|
|
||||||
|
找不到时返回 `-1`。
|
||||||
|
|
||||||
|
### 12.3 `count()`
|
||||||
|
|
||||||
|
`count()` 统计内容出现次数:
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = "Agent Agent Python"
|
||||||
|
print(text.count("Agent"))
|
||||||
|
```
|
||||||
|
|
||||||
|
输出为 `2`。
|
||||||
|
|
||||||
|
### 12.4 开头和结尾判断
|
||||||
|
|
||||||
|
```python
|
||||||
|
file_name = "agent.py"
|
||||||
|
|
||||||
|
print(file_name.startswith("agent"))
|
||||||
|
print(file_name.endswith(".py"))
|
||||||
|
```
|
||||||
|
|
||||||
|
`startswith()` 和 `endswith()` 都返回布尔值。
|
||||||
|
|
||||||
|
## 十三、分割字符串
|
||||||
|
|
||||||
|
`split()` 按照指定分隔符拆分字符串:
|
||||||
|
|
||||||
|
```python
|
||||||
|
technologies = "Python,FastAPI,Django"
|
||||||
|
technology_list = technologies.split(",")
|
||||||
|
|
||||||
|
print(technology_list)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
['Python', 'FastAPI', 'Django']
|
||||||
|
```
|
||||||
|
|
||||||
|
这个结果是列表(List)。列表是可以保存多个数据的容器,将在下一课详细学习。本课只需要知道:`split()` 能把一段文本拆成多个部分。
|
||||||
|
|
||||||
|
如果不提供分隔符,`split()` 会按照连续空白进行分割:
|
||||||
|
|
||||||
|
```python
|
||||||
|
words = "Python Agent 开发".split()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 十四、连接多个字符串
|
||||||
|
|
||||||
|
`join()` 使用指定字符串连接多个文本:
|
||||||
|
|
||||||
|
```python
|
||||||
|
technology_list = ["Python", "FastAPI", "Django"]
|
||||||
|
result = " -> ".join(technology_list)
|
||||||
|
|
||||||
|
print(result)
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Python -> FastAPI -> Django
|
||||||
|
```
|
||||||
|
|
||||||
|
可以这样理解:用 `" -> "` 把列表中的每个字符串连接起来。
|
||||||
|
|
||||||
|
被连接的数据必须是字符串。如果列表中包含整数,直接使用 `join()` 会报 `TypeError`。
|
||||||
|
|
||||||
|
## 十五、字符串判断方法
|
||||||
|
|
||||||
|
常见判断方法:
|
||||||
|
|
||||||
|
| 方法 | 作用 |
|
||||||
|
| --- | --- |
|
||||||
|
| `isdigit()` | 是否全部由数字字符组成 |
|
||||||
|
| `isalpha()` | 是否全部由字母字符组成 |
|
||||||
|
| `isalnum()` | 是否全部由字母或数字字符组成 |
|
||||||
|
| `isspace()` | 是否全部由空白字符组成 |
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```python
|
||||||
|
age_text = "18"
|
||||||
|
|
||||||
|
if age_text.isdigit():
|
||||||
|
age = int(age_text)
|
||||||
|
print(f"年龄:{age}")
|
||||||
|
else:
|
||||||
|
print("请输入整数数字")
|
||||||
|
```
|
||||||
|
|
||||||
|
`isdigit()` 能帮助我们在调用 `int()` 前检查简单的非负整数字符串,但它不能覆盖负数、小数等所有数字形式。
|
||||||
|
|
||||||
|
## 十六、字符串是不可变的
|
||||||
|
|
||||||
|
不可变(Immutable)表示字符串创建后,不能直接修改其中某个字符。
|
||||||
|
|
||||||
|
错误示例:
|
||||||
|
|
||||||
|
```text
|
||||||
|
word = "Agent"
|
||||||
|
word[0] = "a"
|
||||||
|
```
|
||||||
|
|
||||||
|
这会产生 `TypeError`。
|
||||||
|
|
||||||
|
字符串方法通常返回一个新字符串:
|
||||||
|
|
||||||
|
```python
|
||||||
|
original_text = " Python "
|
||||||
|
clean_text = original_text.strip()
|
||||||
|
|
||||||
|
print(original_text)
|
||||||
|
print(clean_text)
|
||||||
|
```
|
||||||
|
|
||||||
|
如果希望变量以后使用处理后的结果,需要重新赋值:
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = text.strip().lower()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 十七、转义字符
|
||||||
|
|
||||||
|
反斜杠 `\` 可以与其他字符组成特殊含义:
|
||||||
|
|
||||||
|
| 写法 | 作用 |
|
||||||
|
| --- | --- |
|
||||||
|
| `\n` | 换行 |
|
||||||
|
| `\t` | 制表符 |
|
||||||
|
| `\"` | 在双引号字符串中表示双引号 |
|
||||||
|
| `\\` | 表示一个反斜杠 |
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```python
|
||||||
|
print("第一行\n第二行")
|
||||||
|
print("名称\t时长")
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows 路径中包含反斜杠。可以使用原始字符串,在开头添加 `r`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
project_path = r"D:\Code\Python"
|
||||||
|
```
|
||||||
|
|
||||||
|
原始字符串会减少反斜杠被当作转义符解释的情况。
|
||||||
|
|
||||||
|
## 十八、多行字符串
|
||||||
|
|
||||||
|
三个双引号或三个单引号可以创建多行字符串:
|
||||||
|
|
||||||
|
```python
|
||||||
|
report = """Agent 学习报告
|
||||||
|
学习方向:Python
|
||||||
|
当前状态:进行中"""
|
||||||
|
|
||||||
|
print(report)
|
||||||
|
```
|
||||||
|
|
||||||
|
多行字符串会保留代码中的换行。需要注意开头和结尾位置,避免无意中加入额外空行。
|
||||||
|
|
||||||
|
## 十九、f-string 格式控制
|
||||||
|
|
||||||
|
f-string 除了插入变量,还能简单控制数字格式:
|
||||||
|
|
||||||
|
```python
|
||||||
|
total_hours = 6.5
|
||||||
|
progress = 0.756
|
||||||
|
|
||||||
|
print(f"总时长:{total_hours:.2f} 小时")
|
||||||
|
print(f"完成率:{progress:.1%}")
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
总时长:6.50 小时
|
||||||
|
完成率:75.6%
|
||||||
|
```
|
||||||
|
|
||||||
|
- `.2f`:浮点数保留两位小数;
|
||||||
|
- `.1%`:转为百分比并保留一位小数。
|
||||||
|
|
||||||
|
这是常用格式,现阶段能够模仿使用即可。
|
||||||
|
|
||||||
|
## 二十、方法链
|
||||||
|
|
||||||
|
多个字符串方法可以连续调用:
|
||||||
|
|
||||||
|
```python
|
||||||
|
raw_answer = " YES "
|
||||||
|
clean_answer = raw_answer.strip().lower()
|
||||||
|
|
||||||
|
print(clean_answer)
|
||||||
|
```
|
||||||
|
|
||||||
|
执行顺序从左到右:
|
||||||
|
|
||||||
|
1. `strip()` 得到 `"YES"`;
|
||||||
|
2. `lower()` 得到 `"yes"`;
|
||||||
|
3. 最终结果保存到 `clean_answer`。
|
||||||
|
|
||||||
|
方法链不宜过长。处理步骤复杂时,可以使用多个含义清晰的中间变量。
|
||||||
|
|
||||||
|
## 二十一、运行本课示例
|
||||||
|
|
||||||
|
在 PowerShell 中执行:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd D:\Code\Python\01_python基础\1_7_字符串
|
||||||
|
python strings.py
|
||||||
|
```
|
||||||
|
|
||||||
|
示例无需用户输入,会依次展示索引、切片、遍历和常用字符串方法。
|
||||||
|
|
||||||
|
## 二十二、常见错误
|
||||||
|
|
||||||
|
### 22.1 索引从 1 开始计算
|
||||||
|
|
||||||
|
Python 字符串第一个字符的索引是 `0`,不是 `1`。
|
||||||
|
|
||||||
|
### 22.2 切片包含结束索引
|
||||||
|
|
||||||
|
切片不包含结束索引。`text[0:3]` 取得索引 `0、1、2`。
|
||||||
|
|
||||||
|
### 22.3 调用方法后忘记保存结果
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = " Python "
|
||||||
|
text.strip()
|
||||||
|
print(text)
|
||||||
|
```
|
||||||
|
|
||||||
|
原变量仍然保留空格。应写成:
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = text.strip()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 22.4 查找内容时忽略大小写
|
||||||
|
|
||||||
|
`"python" in "Python Agent"` 为 `False`。如果业务允许忽略大小写,可以先统一使用 `lower()`。
|
||||||
|
|
||||||
|
### 22.5 混淆 `split()` 和 `join()`
|
||||||
|
|
||||||
|
- `split()`:一个字符串拆成多个部分;
|
||||||
|
- `join()`:多个字符串连接成一个字符串。
|
||||||
|
|
||||||
|
### 22.6 直接修改字符串字符
|
||||||
|
|
||||||
|
字符串不可变,不能执行 `text[0] = "A"`。
|
||||||
|
|
||||||
|
## 二十三、课堂练习
|
||||||
|
|
||||||
|
打开 `practice.py`,完成“Agent 提示词文本分析器”。程序需要清理用户输入,分析长度、关键词、单词数量和文件名,并生成格式化报告。
|
||||||
|
|
||||||
|
运行命令:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python practice.py
|
||||||
|
```
|
||||||
|
|
||||||
|
建议第一次输入:
|
||||||
|
|
||||||
|
```text
|
||||||
|
请使用 Python 帮我开发一个 Agent 应用
|
||||||
|
```
|
||||||
|
|
||||||
|
预期能判断其中包含 `python` 和 `agent` 关键词。判断关键词时应忽略英文大小写。
|
||||||
|
|
||||||
|
## 二十四、思考题
|
||||||
|
|
||||||
|
1. `"Agent"[0]` 和 `"Agent"[-1]` 分别是什么?
|
||||||
|
2. 为什么 `text[0:3]` 不包含索引 `3`?
|
||||||
|
3. `strip()` 会不会删除字符串中间的空格?
|
||||||
|
4. `replace()` 会直接修改原字符串吗?
|
||||||
|
5. `split()` 和 `join()` 的方向有什么不同?
|
||||||
|
6. 为什么字符串方法的返回结果经常需要重新赋值?
|
||||||
|
7. 如何忽略大小写判断文本中是否包含 `python`?
|
||||||
|
|
||||||
|
## 二十五、本课小结
|
||||||
|
|
||||||
|
- 字符串是有顺序的字符集合;
|
||||||
|
- 索引从 `0` 开始,`-1` 表示最后一个字符;
|
||||||
|
- 切片包含开始索引,不包含结束索引;
|
||||||
|
- `len()` 返回字符数量;
|
||||||
|
- 字符串可以使用 `for` 遍历;
|
||||||
|
- `strip()`、`lower()`、`replace()` 等方法返回新字符串;
|
||||||
|
- `in`、`find()`、`count()` 可以查找文本;
|
||||||
|
- `split()` 拆分字符串,`join()` 连接多个字符串;
|
||||||
|
- 字符串不可变,不能直接修改某个字符;
|
||||||
|
- f-string 可以控制小数和百分比格式。
|
||||||
|
|
||||||
|
## 二十六、验收标准
|
||||||
|
|
||||||
|
- [ ] 能使用正索引和负索引读取字符;
|
||||||
|
- [ ] 能使用切片取得字符串的一部分;
|
||||||
|
- [ ] 能使用 `len()` 和 `for` 分析文本;
|
||||||
|
- [ ] 能清理输入并统一英文大小写;
|
||||||
|
- [ ] 能查找和统计指定内容;
|
||||||
|
- [ ] 能使用 `split()` 和 `join()`;
|
||||||
|
- [ ] 能解释字符串不可变;
|
||||||
|
- [ ] 能完成并运行 `practice.py`;
|
||||||
|
- [ ] 能回答七道思考题。
|
||||||
101
01_python基础/1_7_字符串/practice.py
Normal file
101
01_python基础/1_7_字符串/practice.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# 第 1-7 课课堂练习:Agent 提示词文本分析器
|
||||||
|
#
|
||||||
|
# 完成要求:
|
||||||
|
# 1. 根据注释使用字符串索引、切片和常用方法。
|
||||||
|
# 2. 判断英文关键词时忽略大小写。
|
||||||
|
# 3. 使用有意义的英文蛇形变量名。
|
||||||
|
# 4. 不要删除题目注释。
|
||||||
|
# 5. 完成后使用题目提供的文本测试结果。
|
||||||
|
|
||||||
|
# 练习一:使用 input() 接收一段 Agent 提示词。
|
||||||
|
# 将原始输入保存到 raw_prompt。
|
||||||
|
|
||||||
|
# 练习二:使用 strip() 清理提示词两侧空白。
|
||||||
|
# 将结果保存到 clean_prompt。
|
||||||
|
|
||||||
|
# 练习三:使用 len() 统计清理后的字符数量。
|
||||||
|
# 将结果保存到 prompt_length。
|
||||||
|
|
||||||
|
# 练习四:创建用于忽略大小写判断的字符串。
|
||||||
|
# 对 clean_prompt 调用 lower(),将结果保存到 lower_prompt。
|
||||||
|
|
||||||
|
# 练习五:使用 in 完成两个关键词判断:
|
||||||
|
# 1. lower_prompt 是否包含 "python",结果保存到 contains_python;
|
||||||
|
# 2. lower_prompt 是否包含 "agent",结果保存到 contains_agent。
|
||||||
|
|
||||||
|
# 练习六:使用 count() 统计 lower_prompt 中 "agent" 出现的次数。
|
||||||
|
# 将结果保存到 agent_count。
|
||||||
|
|
||||||
|
|
||||||
|
# 练习七:使用 split() 按照空白拆分 clean_prompt。
|
||||||
|
# 不需要给 split() 传入参数。
|
||||||
|
# 将结果保存到 word_list,再使用 len() 统计分割后的数量,保存到 word_count。
|
||||||
|
# 提示:中文句子通常不会按每个汉字拆分;本练习统计的是空白分隔后的文本片段。
|
||||||
|
|
||||||
|
# 练习八:使用索引和切片取得摘要信息。
|
||||||
|
# 先使用 if 判断 prompt_length 是否大于 0,避免空字符串索引越界:
|
||||||
|
# - 非空时:first_character 保存第一个字符,last_character 保存最后一个字符;
|
||||||
|
# - 空字符串时:两个变量都保存 "无"。
|
||||||
|
# 再使用切片 clean_prompt[:10] 取得最多前 10 个字符,保存到 preview_text。
|
||||||
|
|
||||||
|
# 练习九:使用 replace() 将 clean_prompt 中的 "帮我" 替换为 "协助我"。
|
||||||
|
# 将结果保存到 improved_prompt。
|
||||||
|
|
||||||
|
# 练习十:创建字符串 "Python,FastAPI,Django"。
|
||||||
|
# 使用 split(",") 将它拆分并保存到 technology_list。
|
||||||
|
# 再使用 " -> ".join(technology_list) 连接,保存到 technology_path。
|
||||||
|
|
||||||
|
# 练习十一:接收一个 Python 文件名并清理两侧空白。
|
||||||
|
# 使用 endswith(".py") 判断是否为小写 .py 结尾,结果保存到 is_python_file。
|
||||||
|
|
||||||
|
# 练习十二:使用 30 个等号输出分隔线,再使用 f-string 输出分析报告:
|
||||||
|
# 1. 清理后的提示词;
|
||||||
|
# 2. 字符数量 prompt_length;
|
||||||
|
# 3. 文本片段数量 word_count;
|
||||||
|
# 4. 第一个字符和最后一个字符;
|
||||||
|
# 5. 前 10 个字符 preview_text;
|
||||||
|
# 6. 是否包含 Python;
|
||||||
|
# 7. 是否包含 Agent;
|
||||||
|
# 8. Agent 出现次数;
|
||||||
|
# 9. 替换后的提示词 improved_prompt;
|
||||||
|
# 10. 技术路线 technology_path;
|
||||||
|
# 11. 文件名是否以 .py 结尾。
|
||||||
|
|
||||||
|
# 练习十三:根据分析结果输出一条建议:
|
||||||
|
# - clean_prompt 为空:输出“提示词不能为空。”
|
||||||
|
# - 不包含 Agent:输出“建议明确说明 Agent 相关任务。”
|
||||||
|
# - 不包含 Python:输出“建议补充需要使用的编程语言。”
|
||||||
|
# - 同时包含 Agent 和 Python:输出“提示词包含核心技术信息。”
|
||||||
|
# 请使用 if...elif...else,并注意判断顺序。
|
||||||
|
|
||||||
|
|
||||||
|
# 第一次测试建议输入:
|
||||||
|
# 提示词: 请使用 Python 帮我开发一个 Agent 应用
|
||||||
|
# 文件名:agent_service.py
|
||||||
|
#
|
||||||
|
# 预期核心结果:
|
||||||
|
# contains_python = True
|
||||||
|
# contains_agent = True
|
||||||
|
# agent_count = 1
|
||||||
|
# is_python_file = True
|
||||||
|
# 最终建议为“提示词包含核心技术信息。”
|
||||||
|
|
||||||
|
|
||||||
|
# 第二次测试建议输入:
|
||||||
|
# 提示词:请帮我整理学习计划
|
||||||
|
# 文件名:notes.txt
|
||||||
|
#
|
||||||
|
# 预期核心结果:
|
||||||
|
# contains_python = False
|
||||||
|
# contains_agent = False
|
||||||
|
# is_python_file = False
|
||||||
|
# 最终建议优先提示缺少 Agent 相关任务。
|
||||||
|
|
||||||
|
|
||||||
|
# 完成后进行自查:
|
||||||
|
# 1. 是否先 strip() 再进行长度和关键词分析;
|
||||||
|
# 2. 是否使用 lower_prompt 进行英文关键词判断;
|
||||||
|
# 3. 空字符串是否避免了索引越界;
|
||||||
|
# 4. 切片是否最多取得前 10 个字符;
|
||||||
|
# 5. split() 与 join() 的方向是否正确;
|
||||||
|
# 6. 最终建议的判断顺序是否正确。
|
||||||
105
01_python基础/1_7_字符串/strings.py
Normal file
105
01_python基础/1_7_字符串/strings.py
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# 第 1-7 课示例:字符串
|
||||||
|
#
|
||||||
|
# 本文件集中演示字符串索引、切片、遍历和常见方法。
|
||||||
|
# 建议运行后对照每段注释观察结果,不需要用户输入。
|
||||||
|
|
||||||
|
|
||||||
|
# 一、索引
|
||||||
|
# 正索引从 0 开始,负索引从 -1 开始倒数。
|
||||||
|
technology = "Python"
|
||||||
|
print(f"第一个字符:{technology[0]}")
|
||||||
|
print(f"最后一个字符:{technology[-1]}")
|
||||||
|
|
||||||
|
|
||||||
|
# 二、长度
|
||||||
|
# 空格和标点同样会计入字符串长度。
|
||||||
|
prompt = "Python Agent"
|
||||||
|
print(f"提示词长度:{len(prompt)}")
|
||||||
|
|
||||||
|
|
||||||
|
# 三、切片
|
||||||
|
# 切片包含开始索引,不包含结束索引。
|
||||||
|
print(f"前三个字符:{technology[0:3]}")
|
||||||
|
print(f"从索引 3 到末尾:{technology[3:]}")
|
||||||
|
print(f"反转字符串:{technology[::-1]}")
|
||||||
|
|
||||||
|
|
||||||
|
# 四、遍历字符串
|
||||||
|
# for 会依次取得字符串中的每一个字符。
|
||||||
|
for character in "Agent":
|
||||||
|
print(f"当前字符:{character}")
|
||||||
|
|
||||||
|
|
||||||
|
# 五、清理两侧空白并转换大小写
|
||||||
|
raw_text = " Python Agent "
|
||||||
|
clean_text = raw_text.strip()
|
||||||
|
lower_text = clean_text.lower()
|
||||||
|
upper_text = clean_text.upper()
|
||||||
|
|
||||||
|
print(f"清理结果:{clean_text}")
|
||||||
|
print(f"小写结果:{lower_text}")
|
||||||
|
print(f"大写结果:{upper_text}")
|
||||||
|
|
||||||
|
|
||||||
|
# 六、替换文本
|
||||||
|
# replace() 返回新字符串,不会直接修改原字符串。
|
||||||
|
old_goal = "学习 Java 开发"
|
||||||
|
new_goal = old_goal.replace("Java", "Python")
|
||||||
|
|
||||||
|
print(f"原目标:{old_goal}")
|
||||||
|
print(f"新目标:{new_goal}")
|
||||||
|
|
||||||
|
|
||||||
|
# 七、查找和统计
|
||||||
|
analysis_text = "Python Agent Python FastAPI"
|
||||||
|
contains_agent = "Agent" in analysis_text
|
||||||
|
python_position = analysis_text.find("Python")
|
||||||
|
python_count = analysis_text.count("Python")
|
||||||
|
|
||||||
|
print(f"是否包含 Agent:{contains_agent}")
|
||||||
|
print(f"Python 首次出现位置:{python_position}")
|
||||||
|
print(f"Python 出现次数:{python_count}")
|
||||||
|
|
||||||
|
|
||||||
|
# 八、判断开头与结尾
|
||||||
|
file_name = "agent_service.py"
|
||||||
|
print(f"是否以 agent 开头:{file_name.startswith('agent')}")
|
||||||
|
print(f"是否为 Python 文件:{file_name.endswith('.py')}")
|
||||||
|
|
||||||
|
|
||||||
|
# 九、分割与连接
|
||||||
|
# split() 得到列表;列表将在下一课系统学习。
|
||||||
|
technology_text = "Python,FastAPI,Django"
|
||||||
|
technology_list = technology_text.split(",")
|
||||||
|
technology_path = " -> ".join(technology_list)
|
||||||
|
|
||||||
|
print(f"分割结果:{technology_list}")
|
||||||
|
print(f"连接结果:{technology_path}")
|
||||||
|
|
||||||
|
|
||||||
|
# 十、字符串判断方法
|
||||||
|
age_text = "18"
|
||||||
|
code_text = "Agent2026"
|
||||||
|
|
||||||
|
print(f"年龄是否全部为数字:{age_text.isdigit()}")
|
||||||
|
print(f"代码是否只包含字母和数字:{code_text.isalnum()}")
|
||||||
|
|
||||||
|
|
||||||
|
# 十一、方法链
|
||||||
|
# 先清理两侧空白,再统一转为小写。
|
||||||
|
raw_answer = " YES "
|
||||||
|
clean_answer = raw_answer.strip().lower()
|
||||||
|
print(f"标准化回答:{clean_answer}")
|
||||||
|
|
||||||
|
|
||||||
|
# 十二、转义字符和原始字符串
|
||||||
|
print("第一行\n第二行")
|
||||||
|
project_path = r"D:\Code\Python"
|
||||||
|
print(f"项目路径:{project_path}")
|
||||||
|
|
||||||
|
|
||||||
|
# 十三、f-string 数字格式
|
||||||
|
total_hours = 6.5
|
||||||
|
progress = 0.756
|
||||||
|
print(f"总时长:{total_hours:.2f} 小时")
|
||||||
|
print(f"完成率:{progress:.1%}")
|
||||||
10
README.md
10
README.md
@@ -189,11 +189,11 @@ Python/
|
|||||||
## 当前学习进度
|
## 当前学习进度
|
||||||
|
|
||||||
- 当前阶段:第一阶段——Python 基础语法。
|
- 当前阶段:第一阶段——Python 基础语法。
|
||||||
- 当前课程:`1_5_条件判断`。
|
- 当前课程:`1_7_字符串`。
|
||||||
- 当前状态:第五课学习中。
|
- 当前状态:第七课学习中。
|
||||||
- 已完成课程:`1_1_hello_world`、`1_2_变量与数据类型`、`1_3_输入与输出`、`1_4_运算符`。
|
- 已完成课程:`1_1_hello_world` 至 `1_6_循环`。
|
||||||
- 已创建课程目录:`01_python基础/1_1_hello_world/`、`01_python基础/1_2_变量与数据类型/`、`01_python基础/1_3_输入与输出/`、`01_python基础/1_4_运算符/`、`01_python基础/1_5_条件判断/`。
|
- 已创建课程目录:`01_python基础/1_1_hello_world/` 至 `01_python基础/1_7_字符串/`。
|
||||||
- 下一步:阅读第五课讲义、运行分支示例并完成课堂练习。
|
- 下一步:阅读第七课讲义、运行字符串示例并完成课堂练习。
|
||||||
|
|
||||||
## 建议环境
|
## 建议环境
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user