成为 AI 时代的智能协作者
在 AI 编程日益成熟的背景下,Python 学习的目标已从"成为熟练的编码者"转变为"成为能与 AI 高效协作的架构师与质检员"。本课程精简语法、强化数据处理、突出面向对象思维,完全融入与 AI 协作的实践方法。
核心语法与思维:理解 AI 生成的代码
这是与 AI 协作的基石。你无需记忆所有语法细节,但必须能读懂、调试和修改 AI 生成的代码。
1.1 基础语法与数据结构
想象你有一排收纳盒,每个盒子上都贴着一张标签。标签上写着盒子里装的是什么 —— 比如"学习率"、"模型名称"、"训练轮数"。在 Python 中,变量就是标签,它指向内存中存储的数据。
你不需要提前声明盒子的类型(不像 Java 或 C++),Python 会自动判断。这叫做动态类型。
# 变量就像给数据贴标签 model_name = "ResNet50" # 标签 model_name 指向字符串 "ResNet50" learning_rate = 0.001 # 标签 learning_rate 指向浮点数 0.001 num_layers = 50 # 标签 num_layers 指向整数 50 is_training = True # 标签 is_training 指向布尔值 True # 变量可以被重新赋值(标签贴到新的盒子上) learning_rate = 0.0005 # 学习率从 0.001 改为 0.0005 print(learning_rate) # 输出: 0.0005
Python 是动态类型语言,你写 x = 10 时不需要告诉 Python "x 是一个整数",它会自动推断。而 Java 等静态类型语言需要写 int x = 10;。动态类型让代码更简洁,这也是 AI 更喜欢生成 Python 代码的原因之一。
Python 中有四种最常用的基本数据类型,就像生活中有不同种类的容器来装不同类型的物品。
| 数据类型 | 关键字 | 说明 | AI 场景示例 |
|---|---|---|---|
| 整数 | int | 没有小数点的数字 | epochs = 100(训练轮数) |
| 浮点数 | float | 带小数点的数字 | lr = 0.001(学习率) |
| 字符串 | str | 文本,用引号包裹 | optimizer = "adam"(优化器名称) |
| 布尔值 | bool | 只有 True 或 False | use_gpu = True(是否使用GPU) |
# ===== 四种基本数据类型 ===== # 1. 整数 int — 用于计数、索引 batch_size = 32 # 每批训练 32 个样本 num_classes = 10 # 分类任务的类别数 print(type(batch_size)) # <class 'int'> # 2. 浮点数 float — 用于精度、比率 learning_rate = 0.001 # 学习率,需要精确的小数 accuracy = 0.9567 # 模型准确率 95.67% print(type(learning_rate)) # <class 'float'> # 3. 字符串 str — 用于名称、路径、标签 model_name = "BERT" # 模型名称 data_path = "./dataset/" # 数据集路径 print(type(model_name)) # <class 'str'> # 4. 布尔值 bool — 用于开关、判断 use_gpu = True # 是否使用 GPU 加速 is_debug = False # 是否开启调试模式 print(type(use_gpu)) # <class 'bool'> # 类型转换(AI 代码中常见) loss_str = "0.85" # 从日志中读取的字符串 loss_val = float(loss_str) # 转换为浮点数 0.85 epoch_str = "10" # 字符串 "10" epoch_int = int(epoch_str) # 转换为整数 10
运算符是对数据进行操作的符号。Python 提供了三大类运算符,在 AI 代码中几乎无处不在。
| 类别 | 运算符 | 说明 | AI 场景示例 |
|---|---|---|---|
| 算术运算符 | + - * / // % ** | 数学计算 | total_loss = loss1 + loss2 |
| 比较运算符 | == != > < >= <= | 比较大小,返回布尔值 | if accuracy >= 0.9: |
| 逻辑运算符 | and or not | 组合条件判断 | if loss < 0.1 and acc > 0.95: |
# ===== 算术运算符 ===== a, b = 10, 3 print(a + b) # 13 加法 print(a - b) # 7 减法 print(a * b) # 30 乘法 print(a / b) # 3.33 除法(结果为浮点数) print(a // b) # 3 整除(只保留整数部分) print(a % b) # 1 取余(10 除以 3 余 1) print(a ** b) # 1000 幂运算(10 的 3 次方) # ===== 比较运算符 ===== accuracy = 0.92 print(accuracy == 0.92) # True 等于 print(accuracy != 1.0) # True 不等于 print(accuracy >= 0.9) # True 大于等于 print(accuracy < 0.8) # False 小于 # ===== 逻辑运算符 ===== loss = 0.08 acc = 0.96 print(loss < 0.1 and acc > 0.9) # True 两个条件都满足 print(loss < 0.01 or acc > 0.9) # True 至少一个满足 print(not loss < 0.01) # True 取反
print() 用于将信息输出到屏幕,input() 用于从键盘获取用户输入。在 AI 开发中,print() 是调试和监控训练过程的重要工具。
# ===== print() 输出 ===== # 基本输出 print("模型训练开始...") # f-string 格式化输出(推荐!AI 代码中最常用) epoch = 5 loss = 0.234 acc = 0.912 print(f"Epoch {epoch}: loss={loss:.4f}, acc={acc:.2%}") # 输出: Epoch 5: loss=0.2340, acc=91.20% # 多个变量输出 print("Loss:", loss, "Accuracy:", acc) # ===== input() 输入 ===== model_name = input("请输入模型名称: ") print(f"你选择的模型是: {model_name}") # 注意:input() 返回的永远是字符串,需要手动转换 epochs_input = input("请输入训练轮数: ") epochs = int(epochs_input) # 转换为整数 print(f"将训练 {epochs} 轮")
在字符串前加 f,就可以在 {} 中直接嵌入变量。{loss:.4f} 表示保留4位小数,{acc:.2%} 表示显示为百分比并保留2位小数。这是 Python 3.6+ 的语法,AI 生成的代码几乎都使用这种格式。
列表是 Python 中最常用的数据结构之一。你可以把它想象成一个有序的收纳架,每个格子上都有编号(从0开始),你可以往里面放东西、取东西、修改东西。
列表是一个有序的、可修改的元素集合。用方括号 [] 创建。列表中的元素可以是任何类型,甚至可以是不同类型的混合。在 AI 开发中,列表常用于存储训练过程中的损失值、准确率等历史记录。
# ===== 创建列表 ===== loss_history = [0.9, 0.7, 0.5, 0.3, 0.15] # 存储每轮训练的损失值 model_names = ["ResNet", "BERT", "GPT"] # 模型名称列表 empty_list = [] # 空列表 # ===== 索引访问(从 0 开始!)===== print(loss_history[0]) # 0.9 第一个元素 print(loss_history[-1]) # 0.15 最后一个元素(-1表示倒数第一) print(loss_history[-2]) # 0.3 倒数第二个 # ===== 切片(获取一段连续的元素)===== print(loss_history[1:4]) # [0.7, 0.5, 0.3] 索引1到3(不含4) print(loss_history[:3]) # [0.9, 0.7, 0.5] 从开头到索引2 print(loss_history[2:]) # [0.5, 0.3, 0.15] 从索引2到末尾 # ===== 修改元素 ===== loss_history[0] = 0.95 # 把第一个值从 0.9 改为 0.95 # ===== 列表长度 ===== print(len(loss_history)) # 5 列表中有5个元素
列表自带了很多实用的"工具"(方法),可以方便地增删改查。
losses = [0.8, 0.6, 0.4, 0.9, 0.3] # append() — 在末尾添加一个元素 losses.append(0.2) # [0.8, 0.6, 0.4, 0.9, 0.3, 0.2] # insert() — 在指定位置插入元素 losses.insert(0, 1.0) # 在索引0处插入1.0 # [1.0, 0.8, 0.6, 0.4, 0.9, 0.3, 0.2] # remove() — 删除第一个匹配的值 losses.remove(0.9) # 删除值为0.9的元素 # pop() — 弹出指定位置的元素(默认最后一个) last_loss = losses.pop() # 弹出并返回最后一个元素 0.2 first_loss = losses.pop(0) # 弹出并返回第一个元素 1.0 # sort() — 排序(默认升序) losses.sort() # [0.3, 0.4, 0.6, 0.8] losses.sort(reverse=True) # [0.8, 0.6, 0.4, 0.3] 降序 # len() — 获取列表长度 print(len(losses)) # 4
列表推导式是 Python 的"语法糖" —— 用一行代码就能创建列表,比写 for 循环更简洁。AI 生成的代码中大量使用这种写法。
# ===== 基本语法:[表达式 for 变量 in 可迭代对象] ===== # 传统写法 squares = [] for x in range(6): squares.append(x ** 2) # squares = [0, 1, 4, 9, 16, 25] # 推导式写法(一行搞定!) squares = [x ** 2 for x in range(6)] # 结果: [0, 1, 4, 9, 16, 25] # ===== 带条件的推导式 ===== # 只保留偶数的平方 even_squares = [x ** 2 for x in range(10) if x % 2 == 0] # 结果: [0, 4, 16, 36, 64] # ===== AI 场景:处理损失历史 ===== raw_losses = [0.9, 0.7, 0.5, 0.3, 0.15, 0.08] # 筛选出 loss > 0.2 的轮次 high_loss = [l for l in raw_losses if l > 0.2] print(high_loss) # [0.9, 0.7, 0.5, 0.3] # 将所有损失值四舍五入到2位小数 rounded = [round(l, 2) for l in raw_losses] print(rounded) # [0.9, 0.7, 0.5, 0.3, 0.15, 0.08]
当 AI 生成包含列表或字典的代码时,你应重点关注:数据从哪里来、如何被修改、最终流向哪里。这是审查 AI 代码正确性的核心思路。例如,检查 append() 是否在正确的位置被调用,切片范围是否合理。
如果说列表是"带编号的收纳架",那字典就是"带标签的收纳柜"。每个物品都有一个唯一的标签(键,key),通过标签就能快速找到对应的物品(值,value)。
字典是一种键值对(key-value)的存储结构。用花括号 {} 创建,键和值之间用冒号 : 分隔。在 AI 开发中,字典是最常用的配置管理方式 —— 模型的超参数、训练设置等通常都用字典来存储。
# ===== 创建字典 ===== model_config = { "learning_rate": 0.001, # 键: 学习率, 值: 0.001 "batch_size": 32, # 键: 批大小, 值: 32 "epochs": 100, # 键: 训练轮数, 值: 100 "optimizer": "adam", # 键: 优化器, 值: "adam" "use_gpu": True # 键: 是否用GPU, 值: True } # ===== 访问值 ===== print(model_config["learning_rate"]) # 0.001 print(model_config["optimizer"]) # adam # ===== 修改值 ===== model_config["epochs"] = 200 # 把训练轮数改为200 model_config["learning_rate"] = 0.0005 # 调整学习率 # ===== 添加新的键值对 ===== model_config["momentum"] = 0.9 # 新增动量参数 # ===== 删除键值对 ===== del model_config["momentum"] # 删除 momentum # 安全访问(键不存在时不报错,返回默认值) lr = model_config.get("lr", 0.01) # 键"lr"不存在,返回默认值0.01 print(lr) # 0.01
config = { "lr": 0.001, "batch_size": 32, "epochs": 100 } # 方式1:只遍历键(keys) for key in config: print(key) # 输出: lr, batch_size, epochs # 方式2:只遍历值(values) for value in config.values(): print(value) # 输出: 0.001, 32, 100 # 方式3:同时遍历键和值(最常用!) for key, value in config.items(): print(f"{key} = {value}") # 输出: # lr = 0.001 # batch_size = 32 # epochs = 100
字典的键可以是字符串、数字、元组,但不能是列表或字典(因为它们是可变的)。尝试用列表做键会报 TypeError。另外,字典从 Python 3.7 开始保证插入顺序。
- 创建一个列表
temperatures,包含一周7天的气温(如[28, 30, 27, 32, 29, 31, 26]),使用切片获取前3天和后3天的气温,并计算平均气温。 - 创建一个字典
student,包含"name"、"age"、"major"三个键。添加一个新键"grade",然后使用items()遍历并打印所有信息。 - 使用列表推导式,从列表
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]中筛选出所有能被3整除的数,并将它们乘以10。
1.2 程序控制逻辑
如果说变量和数据是程序的"食材",那控制逻辑就是"菜谱的步骤"。通过条件判断和循环,你可以让程序根据不同情况做出不同的反应,或者重复执行某些操作。
条件语句让程序能够"做判断"。就像你出门前会看天气:如果下雨就带伞,否则就不带。Python 用 if、elif、else 三个关键字来实现多分支判断。
# ===== 基本语法结构 ===== accuracy = 0.92 if accuracy >= 0.95: # 条件1:准确率 >= 95% print("模型表现优秀!可以部署") elif accuracy >= 0.85: # 条件2:准确率 >= 85% print("模型表现良好,可继续优化") # ← 命中这个分支 elif accuracy >= 0.70: # 条件3:准确率 >= 70% print("模型表现一般,需要调参") else: # 以上条件都不满足 print("模型表现不佳,建议重新设计")
# ===== and:两个条件都必须满足 ===== loss = 0.08 acc = 0.96 if loss < 0.1 and acc > 0.95: print("训练完成,模型达到目标!") # ===== or:至少一个条件满足即可 ===== gpu_available = False tpu_available = True if gpu_available or tpu_available: print("可以使用加速硬件训练") # ===== not:取反 ===== is_overfitting = False if not is_overfitting: print("模型没有过拟合,继续训练") # ===== 嵌套条件 ===== model_type = "cnn" dataset_size = 50000 if model_type == "cnn": # 外层:判断模型类型 if dataset_size > 10000: # 内层:判断数据量 print("数据充足,CNN 可以发挥优势") else: print("数据量不足,建议数据增强或换模型") elif model_type == "transformer": print("Transformer 模型需要更多数据")
Python 用缩进(通常是4个空格)来表示代码块的层次关系,而不是用大括号 {}。缩进错误是新手最常见的 Bug 之一。建议在编辑器中设置 Tab 键自动转为4个空格。
for 循环用于遍历一个序列(列表、字符串、range 等),对每个元素执行相同的操作。就像你逐个检查流水线上的产品。
# ===== 遍历列表 ===== models = ["ResNet", "BERT", "GPT"] for model in models: print(f"正在加载模型: {model}") # ===== range() 函数详解 ===== # range(stop) — 从 0 到 stop-1 for i in range(5): # 0, 1, 2, 3, 4 print(i, end=" ") # range(start, stop) — 从 start 到 stop-1 for i in range(2, 6): # 2, 3, 4, 5 print(i, end=" ") # range(start, stop, step) — 从 start 到 stop-1,步长为 step for i in range(0, 10, 2): # 0, 2, 4, 6, 8(偶数) print(i, end=" ") # ===== enumerate() — 同时获取索引和值 ===== losses = [0.9, 0.7, 0.5, 0.3] for epoch, loss in enumerate(losses): print(f"Epoch {epoch+1}: loss = {loss}") # 输出: # Epoch 1: loss = 0.9 # Epoch 2: loss = 0.7 # Epoch 3: loss = 0.5 # Epoch 4: loss = 0.3
# ===== AI 场景:模拟模型训练过程 ===== total_epochs = 5 loss = 1.0 # 初始损失值 for epoch in range(total_epochs): loss *= 0.7 # 每轮损失降低30% accuracy = 1.0 - loss # 模拟准确率提升 print(f"Epoch {epoch+1}/{total_epochs} | " Loss: {loss:.4f} | Acc: {accuracy:.2%}")
while 循环在条件为 True 时一直执行,适合"不知道要循环多少次"的场景。就像你一直学习直到考试及格为止。
# ===== 基本语法 ===== count = 0 while count < 5: # 当 count < 5 时持续执行 print(count, end=" ") count += 1 # 一定要修改条件变量!否则死循环 # 输出: 0 1 2 3 4 # ===== AI 场景:持续训练直到损失达标 ===== loss = 1.0 step = 0 target_loss = 0.1 while loss > target_loss: # 只要损失还没达标,就继续训练 loss *= 0.7 # 模拟损失下降 step += 1 # 步数加1 print(f"Step {step}: loss = {loss:.4f}") print(f"经过 {step} 步训练,loss 降至 {loss:.4f},达标!")
for 循环:知道要循环多少次(遍历列表、range)。while 循环:不知道要循环多少次,只知道终止条件(损失达标、用户输入正确密码)。在 AI 训练中,for 循环常用于固定 epoch 数的训练,while 循环常用于早停(Early Stopping)等动态终止策略。
这两个关键字用于在循环中"跳过"或"提前退出",让循环控制更加灵活。
# ===== break:提前退出整个循环 ===== for epoch in range(100): loss = 1.0 / (epoch + 1) if loss < 0.05: # 损失足够低了 print(f"Epoch {epoch+1}: 提前停止!loss={loss:.4f}") break # 立即退出循环 # ===== continue:跳过本次,继续下一次 ===== for i in range(10): if i % 3 == 0: # 跳过能被3整除的数 continue print(i, end=" ") # 输出: 1 2 4 5 7 8 # ===== AI 场景:早停机制(Early Stopping)===== patience = 3 # 容忍连续3轮没有改善 wait = 0 # 等待计数器 best_loss = 999 # 最佳损失(初始设很大) for epoch in range(20): loss = 0.5 / (epoch + 1) + 0.01 * epoch # 模拟先降后升的损失 if loss < best_loss: # 如果当前损失比历史最佳更好 best_loss = loss # 更新最佳损失 wait = 0 # 重置等待计数器 print(f"Epoch {epoch+1}: 新最佳! loss={loss:.4f}") else: # 没有改善 wait += 1 # 等待计数+1 print(f"Epoch {epoch+1}: 无改善 ({wait}/{patience})") if wait >= patience: # 超过容忍次数 print(f"连续 {patience} 轮无改善,提前停止训练!") break # 早停!
早停(Early Stopping)是 AI 训练中非常重要的技术,用于防止过拟合。当 AI 为你生成训练代码时,注意检查 break 的触发条件是否合理 —— 过早停止可能导致模型欠拟合,过晚停止则浪费时间。通常 patience 设为 3~5 比较合理。
- 编写一个程序,使用 for 循环和 if 语句,找出列表
[23, 45, 12, 67, 34, 89, 56]中的最大值和最小值(不要使用内置的max()和min())。 - 使用 while 循环实现一个简单的"猜数字"游戏:设定一个目标数字(如 42),让用户不断输入猜测值,给出"大了"或"小了"的提示,直到猜对为止。
- 使用 for 循环和
enumerate(),遍历模型准确率列表[0.60, 0.72, 0.81, 0.88, 0.91, 0.93, 0.94, 0.94, 0.95],找出准确率首次超过 0.90 的轮次。
1.3 函数
想象你有一份蛋糕食谱:上面写着需要哪些原料、按什么步骤操作。每次你想做蛋糕,只需要按照食谱来,不用重新发明做法。在编程中,函数就是"食谱" —— 把一段有用的代码封装起来,需要时直接调用。
函数由三部分组成:输入(参数) = 原料,处理过程(函数体) = 制作步骤,输出(返回值) = 做好的蛋糕。定义一次,可以反复使用。这避免了代码重复,让程序更清晰、更易维护。
# ===== 定义函数的基本结构 ===== def calculate_accuracy(correct, total): """计算分类准确率 Args: correct: 正确预测的样本数 total: 总样本数 Returns: 准确率(0到1之间的浮点数) """ if total == 0: # 防止除以零 return 0 return correct / total # 返回计算结果 # ===== 调用函数 ===== acc = calculate_accuracy(92, 100) print(f"准确率: {acc:.2%}") # 准确率: 92.00% # ===== 函数命名规范 ===== # 好的命名:动词开头,描述函数做什么 def train_model(data): ... # ✓ 清晰 def load_dataset(path): ... # ✓ 清晰 def tm(d): ... # ✗ 太简短,难以理解
参数是函数的"输入接口",不同类型的参数让函数更加灵活。
# ===== 1. 位置参数(必须按顺序传入)===== def train_model(data, epochs, lr): print(f"用 {data} 训练 {epochs} 轮, 学习率={lr}") train_model("images", 10, 0.001) # 必须按顺序传入3个参数 # ===== 2. 默认参数(不传就用默认值)===== def train_model(data, epochs=10, lr=0.001): print(f"用 {data} 训练 {epochs} 轮, 学习率={lr}") train_model("images") # 使用默认值:10轮, lr=0.001 train_model("images", epochs=50) # 只覆盖 epochs # ===== 3. 关键字参数(用参数名指定,顺序无关)===== train_model(lr=0.01, data="text", epochs=20) # 顺序无关 # ===== 4. 可变参数 *args(接收任意数量的位置参数)===== def compare_models(*accuracies): """比较多个模型的准确率""" for i, acc in enumerate(accuracies): print(f"模型{i+1} 准确率: {acc:.2%}") print(f"最佳: {max(accuracies):.2%}") compare_models(0.85, 0.92, 0.88, 0.95) # 传入任意数量 # ===== 5. 可变关键字参数 **kwargs(接收任意数量的关键字参数)===== def train_with_config(data, **config): """使用配置字典训练模型""" print(f"数据: {data}") for key, value in config.items(): print(f" {key} = {value}") train_with_config("images", epochs=50, lr=0.001, batch_size=32)
# ===== return 语句 ===== def calculate_metrics(correct, total, loss): accuracy = correct / total # 计算准确率 return accuracy # 返回一个值 acc = calculate_metrics(90, 100, 0.3) print(acc) # 0.9 # ===== 返回多个值(元组解包)===== def evaluate_model(predictions, labels): """评估模型,返回多个指标""" correct = sum(1 for p, l in zip(predictions, labels) if p == l) total = len(labels) accuracy = correct / total error_rate = 1.0 - accuracy return accuracy, error_rate, correct # 返回多个值(实际是元组) # 元组解包:用多个变量接收返回值 acc, err, cnt = evaluate_model([1,0,1,1], [1,0,0,1]) print(f"准确率: {acc:.2%}, 错误率: {err:.2%}, 正确数: {cnt}") # 输出: 准确率: 75.00%, 错误率: 25.00%, 正确数: 3
# ===== 局部变量 vs 全局变量 ===== global_lr = 0.001 # 全局变量(在函数外定义) def train(): local_epoch = 10 # 局部变量(在函数内定义) print(f"内部 - 全局lr: {global_lr}") # ✓ 可以读取全局变量 print(f"内部 - 局部epoch: {local_epoch}") # ✓ 可以读取局部变量 train() print(global_lr) # ✓ 全局变量可以在函数外访问 # print(local_epoch) # ✗ 报错!局部变量在函数外不可见 # ===== global 关键字:在函数内修改全局变量 ===== counter = 0 def increment(): global counter # 声明要修改的是全局变量 counter += 1 # 修改全局变量 increment() increment() print(counter) # 2
过度使用 global 会让代码难以调试和维护。在 AI 项目中,建议用类(Class)的属性来管理共享状态,而不是全局变量。好的函数应该是"自包含"的 —— 只通过参数接收输入,只通过返回值输出结果。
Lambda 是一种"匿名函数" —— 没有名字、只有一行的简单函数。常与 map() 和 filter() 配合使用。
# ===== 普通函数 vs Lambda ===== # 普通函数 def square(x): return x ** 2 # Lambda(等价写法,一行搞定) square = lambda x: x ** 2 print(square(5)) # 25 # ===== 配合 map() 使用(对每个元素应用函数)===== numbers = [3, 1, 4, 1, 5] squared = list(map(lambda x: x ** 2, numbers)) print(squared) # [9, 1, 16, 1, 25] # ===== 配合 filter() 使用(筛选满足条件的元素)===== evens = list(filter(lambda x: x % 2 == 0, numbers)) print(evens) # [4] # ===== AI 场景:对损失列表做归一化 ===== losses = [0.9, 0.7, 0.5, 0.3, 0.1] max_loss = max(losses) normalized = list(map(lambda l: l / max_loss, losses)) print(normalized) # [1.0, 0.778, 0.556, 0.333, 0.111]
当函数逻辑很简单(只有一行表达式),且只需要临时使用一次时,用 Lambda。如果逻辑复杂或需要复用,还是写普通函数更清晰。AI 生成的代码中 Lambda 出现频率很高,你需要能读懂它,但不一定要自己写。
在审查 AI 生成的函数代码时,重点关注:函数的输入是什么、输出是什么、中间有没有意外的副作用。比如检查函数是否修改了传入的列表(这可能导致难以发现的 Bug)。好的函数应该像"纯函数"一样:相同输入永远产生相同输出。
- 编写函数
compute_f1(precision, recall),根据精确率和召回率计算 F1 分数。公式:F1 = 2 * precision * recall / (precision + recall)。注意处理分母为零的情况。 - 编写函数
find_best_threshold(losses, thresholds),接收一个损失列表和一组阈值列表,返回使准确率最高的阈值。使用*args或列表推导式。 - 使用 Lambda 和
filter(),从一个包含模型名称的列表["resnet50", "bert_base", "gpt2", "vgg16", "efficientnet"]中筛选出包含数字的名称。
1.4 面向对象编程(OOP)
想象你是一位汽车设计师。你先画一张设计图纸(类,Class),图纸上标注了汽车有几个轮子、什么颜色的漆、能跑多快。然后工厂根据这张图纸,生产出一辆辆真实的汽车(对象,Object)。每辆汽车都是独立的,有自己的状态。
类(Class)是创建对象的模板/蓝图,定义了对象有哪些属性(数据)和方法(行为)。对象(Object)是根据类创建出来的具体实例。在 AI 框架(如 PyTorch)中,每个神经网络模型都是一个类,你创建的每个具体模型就是一个对象。
# ===== 定义一个类 ===== class SimpleModel: """一个简单的AI模型类""" # __init__ 是构造方法 —— 创建对象时自动调用 # self 代表"这个对象自己" def __init__(self, input_size, hidden_size, output_size): # self.属性 = 实例属性(每个对象各自拥有) self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size self.is_trained = False # 默认未训练 print(f"模型已创建: {input_size}→{hidden_size}→{output_size}") # 实例方法 —— 定义对象能做什么 def forward(self, x): """前向传播:数据从输入流向输出""" hidden = [v * 0.5 for v in x] # 模拟隐藏层计算 output = sum(hidden) / len(hidden) # 模拟输出层 return output def train(self): """训练模型""" self.is_trained = True print("模型训练完成!") # __str__ 方法定义了用 print() 打印对象时的显示内容 def __str__(self): return f"SimpleModel({self.input_size}, {self.hidden_size}, {self.output_size})" # ===== 创建对象(实例化)===== model = SimpleModel(input_size=784, hidden_size=128, output_size=10) # ===== 使用对象 ===== print(model) # 调用 __str__ result = model.forward([1.0, 2.0, 3.0]) # 调用方法 print(f"模型输出: {result}") model.train() # 训练模型 print(model.is_trained) # True
self 代表"当前对象自己"。当你写 model.forward(data) 时,Python 实际上在调用 SimpleModel.forward(model, data) —— 自动把 model 作为第一个参数传入。所以类中每个方法的第一个参数都是 self,通过 self.xxx 来访问和修改对象自己的属性。
在真实的 AI 框架中,神经网络模型都遵循一个统一模式:__init__ 中定义网络结构(有哪些层),forward 中定义数据如何流经这些层。这是你必须理解的核心模板。
# ===== 模拟 PyTorch 的 nn.Module 模式 ===== class ImageClassifier: """图像分类模型 —— 模拟 PyTorch 的 nn.Module""" # __init__: 定义模型结构(有哪些层、多少个神经元) def __init__(self, num_classes=10): self.num_classes = num_classes self.layers = [ {"type": "conv", "size": 32}, {"type": "conv", "size": 64}, {"type": "linear", "size": num_classes} ] self.is_built = True print(f"模型构建完成,共 {len(self.layers)} 层,输出 {num_classes} 类") # forward: 定义数据的前向传播路径 def forward(self, x): """数据从输入逐层流向输出""" print(f"输入形状: {x}") for i, layer in enumerate(self.layers): print(f" → 经过第{i+1}层 ({layer['type']}, size={layer['size'])") print(f"输出: {self.num_classes 个类别的概率") return [0.1] * self.num_classes # 模拟输出 # ===== 完整的创建和使用流程 ===== model = ImageClassifier(num_classes=10) # 1. 创建模型 output = model.forward("一张28x28的图片") # 2. 前向传播 print(f"预测结果: {output}")
在 PyTorch 中,每个神经网络都是一个继承自 nn.Module 的类。你必须写 __init__ 定义网络层,写 forward 定义数据流向。理解这个模式,你就能读懂并修改 AI 生成的任何模型代码。这是本课程最重要的知识点。
继承允许你创建一个新类,复用已有类的功能并扩展新功能。就像"电动汽车"继承了"汽车"的所有属性(轮子、方向盘),同时新增了"电池"属性。
# ===== 基类(父类)===== class SimpleModel: def __init__(self, input_size, hidden_size, output_size): self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size def forward(self, x): hidden = [v * 0.5 for v in x] return sum(hidden) / len(hidden) def __str__(self): return f"SimpleModel({self.input_size}, {self.hidden_size}, {self.output_size})" # ===== 子类(继承父类)===== class AdvancedModel(SimpleModel): """高级模型 —— 在简单模型基础上增加 Dropout""" def __init__(self, input_size, hidden_size, output_size, dropout=0.5): # super() 调用父类的 __init__,复用父类的初始化逻辑 super().__init__(input_size, hidden_size, output_size) self.dropout = dropout # 子类新增属性 print(f"高级模型已创建,Dropout率={dropout}") # 方法重写:覆盖父类的 forward 方法 def forward(self, x): hidden = [v * self.dropout for v in x] # 使用 dropout return sum(hidden) / len(hidden) # 子类新增方法 def summary(self): print(f"模型结构: {self.input_size}→{self.hidden_size}→{self.output_size}") print(f"Dropout: {self.dropout}") # ===== 使用继承 ===== adv_model = AdvancedModel(784, 256, 10, dropout=0.3) adv_model.summary() # 调用子类新方法 print(adv_model) # 调用继承的 __str__ result = adv_model.forward([1, 2, 3]) # 调用重写的 forward
封装是"隐藏内部细节,只暴露安全的接口"。就像你用手机不需要知道内部电路怎么走,只需要会按按钮就行。在 Python 中,用私有属性和 @property 装饰器来实现封装。
class TrainingConfig: """训练配置类 —— 通过封装保护关键参数""" def __init__(self): # 双下划线开头 = 私有属性(外部不能直接访问) self.__learning_rate = 0.001 self.__max_epochs = 100 self.__batch_size = 32 # @property 装饰器:让私有属性可以通过"属性"方式安全访问 @property def learning_rate(self): """获取学习率(getter)""" return self.__learning_rate # @xxx.setter 装饰器:设置属性值时进行验证 @learning_rate.setter def learning_rate(self, value): """设置学习率(setter)—— 带验证逻辑""" if value <= 0: raise ValueError("学习率必须大于 0!") if value > 1: raise ValueError("学习率不能大于 1!") self.__learning_rate = value print(f"学习率已更新为: {value}") @property def max_epochs(self): return self.__max_epochs @max_epochs.setter def max_epochs(self, value): if value < 1: raise ValueError("训练轮数至少为 1!") self.__max_epochs = value # ===== 使用封装 ===== config = TrainingConfig() # 读取属性 print(config.learning_rate) # 0.001(通过 @property 访问) # 设置属性(会自动验证) config.learning_rate = 0.0005 # ✓ 合法值 # config.learning_rate = -0.1 # ✗ 会报错:ValueError # config.learning_rate = 2.0 # ✗ 会报错:ValueError # 直接访问私有属性会失败(名称被改写) # print(config.__learning_rate) # ✗ 报错!
Python 的双下划线私有属性实际上是通过"名称改写"(name mangling)实现的,__lr 会被改写为 _ClassName__lr。所以严格来说仍然可以通过 config._TrainingConfig__learning_rate 访问。Python 的封装更多是"约定"而非"强制",靠的是开发者自觉。
面向对象编程有三大核心概念:封装(隐藏细节、保护数据)、继承(复用代码、扩展功能)、多态(同一方法在不同类中有不同行为)。本节重点讲了封装和继承。在 AI 框架中,你经常看到继承(自定义模型继承 nn.Module)和封装(通过 property 保护超参数)。
- 创建一个
Dataset类,包含__init__(self, name, size)、get_info()(返回数据集名称和大小)和__str__()方法。创建两个不同的 Dataset 对象并打印。 - 创建一个基类
BaseOptimizer,包含__init__(self, lr)和step()方法。创建子类Adam(BaseOptimizer),在step()中打印"Adam 更新参数,lr=xxx"。使用super()调用父类初始化。 - 创建一个
ModelConfig类,使用私有属性和@property封装dropout_rate(必须在 0 到 1 之间)。尝试设置非法值(如 1.5),观察报错信息。
数据处理三剑客:与 AI 协作的实战工具
AI 应用前 90% 的时间都在处理数据。掌握 NumPy、Pandas、Matplotlib 是为 AI 准备"弹药"并理解其输出的关键。
NumPy — 数值计算
NumPy 数组(ndarray)是所有张量运算的基础。图像在计算机中就是一个多维 NumPy 数组。理解其"广播机制"可以实现并行计算。
import numpy as np # 创建数组 a = np.array([1, 2, 3, 4]) # 一维数组 matrix = np.array([[1, 2], [3, 4]]) # 二维矩阵 zeros = np.zeros((3, 3)) # 3×3 全零矩阵 rand = np.random.rand(2, 3) # 2×3 随机矩阵 # 数组运算(向量化,比循环快 100 倍) scores = np.array([85, 92, 78, 95, 88]) print(scores.mean()) # 87.6 均值 print(scores.std()) # 标准差 print(scores.max()) # 95 最大值 print(np.argmax(scores)) # 3 最大值索引 # ★ 广播机制 — 不同形状的数组自动对齐运算 data = np.array([[1, 2], [3, 4], [5, 6]]) bias = np.array([10, 20]) print(data + bias) # [[11 22] # [13 24] # [15 26]] # 索引与切片 img = np.zeros((28, 28)) # 模拟 28×28 灰度图像 print(img[0:14, :]) # 上半部分 print(img.shape) # (28, 28)
Pandas — 数据分析
重点掌握 DataFrame 和 Series 数据结构,以及数据读取、清洗、筛选和基本统计分析。这是处理表格数据(CSV、Excel)的标准工具,直接关系到输入 AI 的数据质量。
import pandas as pd # 创建 DataFrame df = pd.DataFrame({ "name": ["样本A", "样本B", "样本C", "样本D"], "feature_1": [1.2, 3.4, 2.1, 4.5], "feature_2": [5.6, 7.8, None, 9.0], # 含缺失值 "label": [0, 1, 0, 1] }) # 读取文件(最常用操作) # df = pd.read_csv("data.csv") # df = pd.read_excel("data.xlsx") # 数据概览 print(df.head(2)) # 前 2 行 print(df.info()) # 数据类型和缺失值 print(df.describe()) # 统计摘要 # ★ 数据清洗 — 处理缺失值 print(df.isnull().sum()) # 查看缺失值数量 df["feature_2"] = df["feature_2"].fillna(df["feature_2"].mean()) # 均值填充 # 数据筛选 high = df[df["feature_1"] > 2.0] # 条件筛选 cols = df[["name", "label"]] # 选择列 # 分组统计 print(df.groupby("label")["feature_1"].mean())
AI 生成的数据处理代码中,Pandas 操作是最常见的。你应重点关注:fillna() 如何处理缺失值、groupby() 如何聚合数据、筛选条件是否正确。数据质量直接决定 AI 模型的效果。
Matplotlib — 数据可视化
掌握基础绘图(折线图、柱状图、散点图),用于可视化分析结果和监控 AI 模型的训练过程(如绘制 Loss 曲线、准确率曲线)。
import matplotlib.pyplot as plt # ★ 绘制训练 Loss 曲线 — AI 训练中最常用的图 epochs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] train_loss = [0.9, 0.7, 0.5, 0.4, 0.3, 0.25, 0.2, 0.18, 0.15, 0.12] val_loss = [0.85, 0.72, 0.55, 0.45, 0.38, 0.35, 0.33, 0.32, 0.31, 0.30] plt.figure(figsize=(8, 5)) plt.plot(epochs, train_loss, 'b-', label='训练损失') plt.plot(epochs, val_loss, 'r--', label='验证损失') plt.xlabel('Epoch') plt.ylabel('Loss') plt.title('模型训练过程') plt.legend() plt.grid(True, alpha=0.3) plt.show() # 散点图 — 查看数据分布 x = [1, 2, 3, 4, 5] y = [2.1, 3.9, 6.2, 7.8, 10.1] plt.scatter(x, y, color='green', s=80) plt.show()
与 AI 协同的实践方法与高级概念
贯穿"以 AI 为伴"的学习理念,并点明关键的高级概念,让你能读懂更 Pythonic 的 AI 生成代码。
项目驱动,AI 辅助
采用"项目驱动,AI 辅助"的学习模式。从设定一个简单的数据分析或自动化小目标开始,利用 AI 生成初始代码,你的重点在于理解代码意图、调试错误和优化逻辑。这比单纯学习语法更高效。
第一步:向 AI 描述你的目标(如"帮我分析一份销售数据的趋势")→ 第二步:AI 生成初始代码 → 第三步:逐行阅读,标注不理解的部分 → 第四步:向 AI 提问,理解每一行 → 第五步:运行、调试、优化 → 第六步:总结学到的知识点。
模块与包管理
如何导入和使用第三方库(如用 pip 安装)。这是使用 AI 生态工具的基础。
# 终端中安装第三方库 # pip install numpy pandas matplotlib scikit-learn # Python 中导入 import numpy as np # 标准别名 from pandas import DataFrame # 导入特定类 from sklearn.model_selection import train_test_split # 深层导入 # 查看已安装的包 # pip list # pip show numpy
文件操作与异常处理
读写文件(CSV、JSON)和捕获处理程序运行中的错误,保证程序健壮性。
import json # ★ JSON — AI 配置和数据交换的标准格式 config = { "model": "resnet50", "batch_size": 32, "epochs": 100 } # 写入 JSON with open("config.json", "w", encoding="utf-8") as f: json.dump(config, f, indent=2) # 读取 JSON with open("config.json", "r", encoding="utf-8") as f: loaded = json.load(f) print(loaded["model"]) # 'resnet50' # ★ 异常处理 — 让程序不轻易崩溃 try: df = pd.read_csv("data.csv") result = df.describe() except FileNotFoundError: print("错误:找不到数据文件,请检查路径") except Exception as e: print(f"未知错误:{e}") else: print("数据处理成功!") finally: print("程序执行完毕。")
迭代器、生成器与装饰器
了解这些概念,有助于阅读更高效、更 Pythonic 的 AI 生成代码。无需深入编码,但需认识其语法模式。
# ★ 生成器 — 按需生成数据,节省内存 def data_batch_generator(data, batch_size=32): """逐批生成数据,AI 训练中常用模式""" for i in range(0, len(data), batch_size): yield data[i:i+batch_size] # 使用生成器 data = list(range(100)) for batch in data_batch_generator(data, batch_size=30): print(f"批次大小: {len(batch)}") # ★ 装饰器 — 不修改函数代码的情况下增强功能 import time def timer(func): """计时装饰器 — 监控函数执行时间""" def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"{func.__name__} 耗时: {end-start:.2f}秒") return result return wrapper @timer # 使用装饰器 def train_model(): time.sleep(1.5) # 模拟训练 train_model() # 输出: train_model 耗时: 1.50秒
AI 生成的代码中经常出现 yield(生成器)、@ 开头的装饰器语法。你不需要自己写这些,但必须能识别它们并理解其作用,这样才能正确审查 AI 代码。
衔接 AI:传统机器学习入门
了解传统机器学习是理解 AI 世界的重要背景。Scikit-learn 封装了经典算法,了解其统一模式有助于快速使用 AI 生成的 ML 代码。
传统 ML 的价值
在数据量小、需要模型可解释性时,传统 ML 仍是重要选择。Scikit-learn 是最经典的 Python 机器学习库,它封装了线性回归、决策树、随机森林、SVM 等经典算法。
| 场景 | 推荐算法 | 特点 |
|---|---|---|
| 预测连续值(房价、温度) | 线性回归 | 简单、可解释性强 |
| 分类问题(垃圾邮件检测) | 逻辑回归 / 决策树 | 速度快、易于理解 |
| 小数据集、高精度需求 | 随机森林 / SVM | 鲁棒性强、泛化好 |
| 数据量充足、复杂模式 | 深度学习 | 需要 GPU、大量数据 |
Scikit-learn 实战
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report # 1. 加载数据 iris = load_iris() X = iris.data # 特征矩阵 (150×4) y = iris.target # 标签 (150,) # 2. 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) # 3. 实例化模型 model = RandomForestClassifier(n_estimators=100) # 4. 拟合(训练) model.fit(X_train, y_train) # 5. 预测 y_pred = model.predict(X_test) # 6. 评估 print(f"准确率: {accuracy_score(y_test, y_pred):.2%}") print(classification_report(y_test, y_pred))
统一模式:实例化 → 拟合 → 预测
Scikit-learn 的所有算法都遵循同一个模式。掌握这个模式,你就能快速使用 AI 生成的任何 ML 代码。
# ★ Scikit-learn 的统一模式(所有算法通用) # 第一步:实例化(选择算法并设置参数) from sklearn.linear_model import LinearRegression model = LinearRegression() # 第二步:拟合(用训练数据学习规律) model.fit(X_train, y_train) # 第三步:预测(对新数据做出判断) predictions = model.predict(X_test) # 换一个算法?只需改第一步! from sklearn.tree import DecisionTreeClassifier model = DecisionTreeClassifier() model.fit(X_train, y_train) predictions = model.predict(X_test)
当 AI 为你生成机器学习代码时,你只需检查三件事:① 数据是否正确划分了训练集和测试集?② fit() 的输入特征和标签是否对应?③ 评估指标是否合理?掌握了这个思路,你就能成为 AI 代码的合格"质检员"。
恭喜你完成了本课程!你已经掌握了 AI 时代 Python 协作者的核心能力:能读懂 AI 生成的代码(语法 + OOP)、能为 AI 准备高质量数据(NumPy + Pandas)、能可视化分析结果(Matplotlib)、能管理项目和处理异常、能快速上手传统 ML(Scikit-learn)。记住:你的目标不是成为熟练的编码者,而是成为能精准向 AI 描述需求、能批判性评估和优化其代码输出的"智能时代协作者"。