1.1 从手写到生成:AI 编码的效率差
我写 Python 五年了,日常工作里堆着各种脚本:批量改文件名、抓网页、洗 Excel、跑定时任务。这些活儿谈不上多难,但加起来很耗时间。一个批量重命名脚本,手写加调试少说半小时;碰到正则表达式不熟的场景,翻文档的时间比写代码还长。
AI 大模型火起来之后,我做了一个实验:同一个需求,一半手写,一半让 AI 生成,把耗时和返工情况都记下来。跑了两个星期,结论很有意思——AI 生成的初版确实快,但离直接能用还有距离,真正的效率差体现在后续的修改和排查上。这篇就聊聊这个实验的过程、数据和结论。
场景:一个批量重命名脚本
需求很典型:目录下有一堆照片,文件名是 IMG_20231001_153022.jpg 这种格式,我想改成 2023-10-01_15-30-22_001.jpg,也就是日期加分隔符、时间部分下划线换横杠,再带个序号前缀防止同名冲突。
手写的话,我会先写个大概,然后查 os.rename 的参数顺序、确认 re.sub 的分组写法,再跑一遍小样本验证。从打开编辑器到跑通,大概 25 分钟。
让 AI 生成呢?把需求描述丢过去,30 秒出结果。这里值得对比一下两份代码的形态。手写版本我会习惯性地先写正则:
import os
import re
def batch_rename_manual(folder):
pattern = re.compile(r"IMG_(\d{8})_(\d{6})\.jpg")
for i, name in enumerate(sorted(os.listdir(folder)), 1):
m = pattern.match(name)
if not m:
continue
d, t = m.group(1), m.group(2)
new = "%s-%s-%s_%s-%s-%s_%03d.jpg" % (d[:4], d[4:6], d[6:8], t[:2], t[2:4], t[4:6], i)
os.rename(os.path.join(folder, name), os.path.join(folder, new))
AI 给出的版本没用正则,而是直接切片加 split:
import os
def batch_rename(folder):
seq = 0
for name in sorted(os.listdir(folder)):
if not name.startswith("IMG_"):
continue
part = name[4:-4]
date, time = part.split("_")
seq += 1
new = f"{date[:4]}-{date[4:6]}-{date[6:8]}_{time[:2]}-{time[2:4]}-{time[4:6]}_{seq:03d}.jpg"
os.rename(os.path.join(folder, name), os.path.join(folder, new))
两份都能跑,结果一模一样,耗时却是 25 分钟对 30 秒,接近 50 倍。有意思的是 AI 的写法我没想过——切片在这类固定格式上比正则更直白,这算是生成代码带的一点额外收获。
方案:双轨对照实验
单个例子说服力有限,我连续两周把每天的中小脚本都做双轨记录:一方面估算纯手写耗时,一方面记录 AI 生成加实际修改的耗时,同时标记返工次数。统计下来得到一张表:
| 脚本类型 | 手写耗时 | AI 生成加修改 | 返工率 | 备注 |
|---|---|---|---|---|
| 批量重命名 | 25 分钟 | 4 分钟 | 低 | 模式清晰,AI 最擅长 |
| 网页抓取解析 | 40 分钟 | 12 分钟 | 中 | 反爬和编码问题要人工兜底 |
| Excel 清洗 | 35 分钟 | 10 分钟 | 低 | pandas 固定套路,质量高 |
| 定时任务改写 | 20 分钟 | 8 分钟 | 低 | 模板化代码 |
| 日志分析脚本 | 30 分钟 | 9 分钟 | 低 | 正则加聚合,典型场景 |
| 异步并发重构 | 60 分钟 | 45 分钟 | 高 | 上下文一长就跑偏 |
| 复杂状态机 | 90 分钟 | 80 分钟 | 很高 | 改到最后自己重写更快 |
规律很明显:越是模式化、模板化的脚本,AI 的效率差越大,能省 70% 以上的时间;越是涉及业务上下文和状态流转的代码,优势越小,有时候甚至是负收益。
基于这组数据,我把日常工作流改成了三分法。第一类是纯模式化任务,比如文件批处理、格式转换、固定格式的报表清洗,这类需求描述短、验收标准清楚,直接整段交给 AI 生成初版,我做一轮审查就合并。第二类是半模式化任务,比如网页抓取、日志分析,骨架我来定,具体函数和正则交给 AI 写,出了问题责任边界清楚。第三类是核心逻辑,比如状态机、并发控制、与业务规则强耦合的部分,这类我自己写,最多让 AI 帮忙补单元测试和边界用例。
这个分类看着简单,但它是用两周返工时间换来的。刚开始图快,什么活儿都丢给 AI,结果第三类任务返工最狠——生成代码改到第三遍的时候,不如推翻重写。承认 AI 有不擅长的领域,反而是效率提升的开始。
为了把数据记准,我还写了个计时小工具,每次任务开始前按一下:
import time
from contextlib import contextmanager
@contextmanager
def track(name, log="timings.csv"):
start = time.time()
yield
cost = round((time.time() - start) / 60, 2)
with open(log, "a", encoding="utf-8") as f:
f.write(f"{name},{cost}\n")
用起来就是 with track("rename") 包住 batch_rename(folder),两周下来数据全在 CSV 里,画个图就有了上面这张表。
这套做法后来贯穿了整个工具箱项目,从 第二章的批处理脚本 一直用到 第四篇的云端部署。说句题外话,如果你刚接触云服务器,轻量应用服务器建站指南 里有从零开始的环境配置,和本章的脚本是同一条链路。
踩坑:生成快不等于能用快
效率差不能只看初版速度,我踩过几个典型的坑,每一个都把省下的时间又赔回去一部分。
第一个是幻觉 API。AI 给过一个 os.rename 的高级用法,说可以跨目录批量移动并自动创建目标目录。代码看着很像那么回事,实际 os.rename 根本没有这个行为,跨盘还会直接报错。跑了一下才发现,又花 15 分钟排查。这类坑在标准库上特别多,AI 会把不同库的接口混着编。
第二个是边界条件缺失。上面的重命名脚本,如果目录里已经存在同名文件,rename 会无声无息地覆盖掉。手写时我会下意识想到这个问题,AI 不会主动加。后来我养成了一个习惯:拿到生成代码先问一句如果文件已存在会怎样、如果目录为空会怎样,再让它补上判断。
第三个是上下文丢失。脚本一旦超过两三百行,或者依赖项目里其他模块,AI 就开始自作主张,编出不存在的函数名和配置项。有一次它给我引用了一个 utils.load_config 函数,写得有模有样,但项目里压根没有这个文件,跑起来直接 ImportError。这个在 1.3 代码审查 那篇会展开讲怎么兜住,这里先记住一个原则:任务拆得越短,AI 越可靠。
我把这些坑整理成一张自检清单,每次拿到生成代码先过一遍:
| 检查项 | 什么时候查 | 常见问题 |
|---|---|---|
| API 是否真实存在 | 生成后立即看 | 编造的标准库方法 |
| 边界与异常路径 | 跑通之后 | 覆盖、空值、越界 |
| 错误处理 | 合并代码前 | 只有正常路径,出错就崩 |
| 依赖与上下文 | 超过百行时 | 引用不存在的函数 |
小结
AI 编码的效率差是真实的,但不是均匀分布的:模板化脚本能省七成以上的时间,复杂逻辑可能只省一成,甚至倒贴。关键是用对场景,并且把省下来的时间投到代码审查上,而不是盲目信任生成结果。下一篇 1.2 提示词工程 会讲怎么把需求说清楚——提示词的质量直接决定初版代码的质量,是效率差能否兑现的第一道关口。
如果你想把工具箱也搬到云上跑,可以看看 腾讯云 AI 办公助手活动页,新用户有些特惠,我最早的一台服务器就是活动价入手的。
