AI建了三个任务为何都做最后一个?
让AI写一个批处理脚本,循环里明明创建了三个任务,最后都处理同一个文件。任务数量没少,程序也没有报错,问题可能不在模型或队列,而在回调函数读取变量的时间。
我在Python 3.9.6里做了实验:在函数内部遍历A、B、C,每一轮把lambda: item加入任务列表,等循环结束后再逐个调用。你可能期待A、B、C,实际得到的却是C、C、C。函数对象不同,但它们读取的是同一个外层变量。
Python官方编程FAQ专门解释了这种行为:函数使用外层变量时,通常在调用阶段读取它的值,而不是定义函数时自动保存一份。当循环已经结束,item最后指向C,稍后执行的三个回调便都读到C。这常被称为闭包的晚绑定问题。
可以比喻为,给每个任务留了一张“去看白板上当前名字”的纸条,而不是各自抄下当时的名字。等大家开始执行,白板上只剩最后一项。纸条有三张,并不意味着三张纸条保存了三个不同的名字。
在AI生成的自动化代码中,这可能影响文件处理、按钮回调和延后执行的评测任务。尤其要留意“先循环创建函数,再统一调用”的结构。如果在每一轮循环里立刻调用,变量尚未变化,简单测试可能看不出问题;推迟执行后才暴露。
对这个例子,可以写成lambda item=item: item。右侧默认值在函数定义时求值,每个回调因此绑定当轮的字符串。用相同输入重新测试,结果就恢复成A、B、C。这里讨论的是不传参数地调用这些回调;显式传入参数仍可以覆盖默认值。
但不要把这招理解成自动复制全部数据。若绑定的是列表或字典,默认参数保留的是当时那个对象的引用,之后对对象内容的修改仍可能被看到。想要不可变的任务描述,可以优先保存独立的文件路径、编号等字段,并明确哪些内容允许后续变化。
另一种设计是用一个工厂函数接收当前参数,再返回对应的任务函数,让每次工厂调用形成独立的参数绑定。也可以让任务执行器显式接收函数与参数,减少依赖外部循环变量。选择取决于接口与数据生命周期。
验证时不要只数“创建了几个任务”。记录每个任务真正收到的输入标识,再检查是否覆盖预期集合、是否出现重复。用至少三个不同输入,在循环完全结束后执行,才能覆盖这个错误典型触发条件。
AI把循环写出来,只完成了表面结构。任务何时读取参数、参数绑定到哪里,决定了最后做的是不是你交代的那件事。
人工智能 Python 自动化 编程技巧
