预计 40 分钟|前置:Class 2 环境可用|产物:
02_basics.py+ 会统计字频
0. 本章目标
只学训练和数据处理真正用得到的 Python:
变量、字符串、列表、字典、条件、循环 。
学完你能读懂「统计数据集」这类脚本的一半代码。
1. 运行脚本
powershell
chcp 65001 | Out-Null
$env:PYTHONUTF8="1"; $env:PYTHONIOENCODING="utf-8"
[Console]::OutputEncoding=[Text.Encoding]::UTF8
& "D:\miniconda3\envs\llm\python.exe" "D:\myAImodle\Class03\Chapter01\02_basics.py"
2. 预期输出
=== 1. 变量与类型 ===
Qwen3 <class 'str'>
0.6 <class 'float'>
True <class 'bool'>
=== 2. 字符串 ===
模型微调是让预训练模
模型LoRA是让预训练模型适应特定任务的方法。LoRA需要数据,数据质量决定模型效果。
文本长度: 39 字
=== 3. list ===
['Qwen3-0.6B', 'Qwen3-1.7B', 'Qwen3-4B']
第一个: Qwen3-0.6B, 最后一个: Qwen3-8B, 共 4 个
=== 4. dict ===
Qwen3-0.6B
未记录
name: Qwen3-0.6B
params: 0.6
unit: B
=== 5. if/elif/else ===
分数 82: 及格
=== 6. dict + for:统计字频 ===
模: 3
型: 3
微: 2
调: 2
定: 2
=== 7. enumerate ===
1 Qwen3-0.6B
2 Qwen3-1.7B
3 Qwen3-4B
4 Qwen3-8B
3. 完整代码
python
text = "模型微调是让预训练模型适应特定任务的方法。微调需要数据,数据质量决定模型效果。"
print("=== 1. 变量与类型 ===")
name = "Qwen3"
param_count = 0.6
is_open = True
print(name, type(name))
print(param_count, type(param_count))
print(is_open, type(is_open))
print("\n=== 2. 字符串 ===")
print(text[:10])
print(text.replace("微调", "LoRA"))
print(f"文本长度: {len(text)} 字")
print("\n=== 3. list ===")
models = ["Qwen3-0.6B", "Qwen3-1.7B", "Qwen3-4B"]
print(models)
models.append("Qwen3-8B")
print(f"第一个: {models[0]}, 最后一个: {models[-1]}, 共 {len(models)} 个")
print("\n=== 4. dict ===")
model_info = {"name": "Qwen3-0.6B", "params": 0.6, "unit": "B"}
print(model_info["name"])
print(model_info.get("context", "未记录"))
for key, value in model_info.items():
print(f"{key}: {value}")
print("\n=== 5. if/elif/else ===")
score = 82
if score >= 90:
level = "优秀"
elif score >= 60:
level = "及格"
else:
level = "不及格"
print(f"分数 {score}: {level}")
print("\n=== 6. dict + for:统计字频 ===")
punctuation = "。,、;:!? "
counter = {}
for ch in text:
if ch in punctuation:
continue
counter[ch] = counter.get(ch, 0) + 1
top5 = sorted(counter.items(), key=lambda item: item[1], reverse=True)[:5]
for ch, count in top5:
print(f"{ch}: {count}")
print("\n=== 7. enumerate ===")
for i, model in enumerate(models, start=1):
print(i, model)
4. 逐块拆解
第 1 块:变量与类型
python
name = "Qwen3"
param_count = 0.6
is_open = True
name = "Qwen3":把字符串存进变量name。param_count = 0.6:浮点数(带小数)。is_open = True:布尔值,只有True/False,首字母大写。
三种最常见的类型:
| 类型 | 写法 | 用途 |
|---|---|---|
str |
"文本" |
文本、路径、JSON |
float / int |
0.6 / 42 |
数字 |
bool |
True / False |
条件判断 |
print(name, type(name)) 里的 type() 返回类型,输出 <class 'str'>。
命名规则:字母、数字、下划线,不能数字开头,区分大小写;习惯用小写下划线(param_count)。
第 2 块:字符串
python
print(text[:10])
print(text.replace("微调", "LoRA"))
print(f"文本长度: {len(text)} 字")
text[:10]:切片,取下标 0~9,不含 10。replace("微调", "LoRA"):返回一个新字符串,原字符串不变。len(text):字符数(不是字节数)。f"...":f-string,花括号里可以放变量或表达式。
第 3 块:list(列表)
python
models = ["Qwen3-0.6B", "Qwen3-1.7B", "Qwen3-4B"]
models.append("Qwen3-8B")
print(models[0], models[-1], len(models))
[]:有序、可重复、可修改。- 下标从 0 开始;
-1表示最后一个。 append():在末尾追加,直接修改原列表。len():元素个数。
第 4 块:dict(字典)
python
model_info = {"name": "Qwen3-0.6B", "params": 0.6, "unit": "B"}
print(model_info["name"])
print(model_info.get("context", "未记录"))
for key, value in model_info.items():
print(f"{key}: {value}")
{键: 值}:按键取值,适合描述「一个对象」。model_info["name"]:键不存在会抛KeyError。.get("context", "未记录"):键不存在返回默认值,不报错。.items():同时拿到键和值,配合for key, value in ...解包。
处理 JSON 数据时,字典就是主力结构;
.get()是防报错的第一招。
第 5 块:if / elif / else
python
if score >= 90:
level = "优秀"
elif score >= 60:
level = "及格"
else:
level = "不及格"
- 从上往下判断,第一个成立的分支执行,后面的跳过。
- 冒号
:不能少,下一行必须缩进(4 个空格)。 =是赋值,==才是比较;>=是大于等于。
第 6 块:用 dict + for 统计字频
python
punctuation = "。,、;:!? "
counter = {}
for ch in text:
if ch in punctuation:
continue
counter[ch] = counter.get(ch, 0) + 1
逐行看:
| 代码 | 含义 |
|---|---|
counter = {} |
空字典,准备存「字 → 次数」 |
for ch in text: |
逐个字符遍历字符串 |
if ch in punctuation: |
这个字是标点吗 |
continue |
是标点就跳过,进入下一轮 |
counter.get(ch, 0) |
取当前次数,没有就当 0 |
+ 1 |
次数加一 |
counter[ch] = ... |
写回字典 |
这一行是全文核心:
python
counter[ch] = counter.get(ch, 0) + 1
等价于:
python
old = counter.get(ch, 0)
counter[ch] = old + 1
第 7 块:排序取前 5
python
top5 = sorted(counter.items(), key=lambda item: item[1], reverse=True)[:5]
counter.items():变成[("模", 3), ("型", 3), ...]。sorted(..., key=..., reverse=True):按指定规则降序排序。lambda item: item[1]:匿名函数,取元组的第 2 项(次数)作为排序依据。[:5]:取前 5 个。
lambda 可以先理解成「一行的临时函数」,等价于:
python
def get_count(item):
return item[1]
第 8 块:enumerate
python
for i, model in enumerate(models, start=1):
print(i, model)
enumerate:遍历时同时给出「序号 + 元素」。start=1:序号从 1 开始;不写默认从 0。i, model:元组解包。
5. 常见错误
| 报错/现象 | 原因 | 解决 |
|---|---|---|
IndentationError |
缩进不一致/漏缩进 | 统一 4 个空格,别混 Tab |
KeyError: 'context' |
字典没有这个键 | 用 .get("context", 默认值) |
TypeError: can only concatenate str |
字符串直接加数字 | 用 f-string 或 str(数字) |
| 统计结果包含标点 | 标点集合没写全 | 把中文标点补进 punctuation |
if score = 90: |
把比较写成赋值 | 改成 == 或 >= |
NameError: name 'x' is not defined |
变量没定义/拼错 | 检查拼写和作用域 |
6. 练习(改代码观察输出)
- 把
text改成"大模型微调大模型",重新运行,字频结果是什么? - 把
score改成 95,输出应该是什么? - 再给
models追加一个"Qwen3-14B",总数变成几?
7. 验收清单
- 脚本能完整运行,无报错
- 能解释
counter.get(ch, 0) + 1 - 能说出
[]和{}的区别 - 能解释
lambda item: item[1]在按什么排序 - 三道练习全对
8. 下一章
Class 3 Chapter 2:函数、异常处理、文件读写------把今天的代码封装成可复用函数。
附:练习答案
大: 2,模: 3,型: 2,微: 1,调: 1(顺序按首次出现,次数相同看原顺序)。分数 95: 优秀,因为95 >= 90先命中。- 5 个;
append后len(models)为 5。