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 办公助手活动页,新用户有些特惠,我最早的一台服务器就是活动价入手的。

延伸阅读