You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重复赋值指向可迭代对象的变量为何导致Python代码结果异常

问题原因分析

用户提供的代码如下:

import more_itertools as mo

def rep(x, n):
    for i in range(n):
        yield x

xs = [0]
for n in [1, 2, 3]:
    xs = mo.flatten(rep(x, n) for x in xs)

print(mo.ilen(xs))

预期逻辑的错误假设

预期输出6的前提是:每次循环都会立刻对xs求值,用当前循环的n值计算新的xs长度:

  • 第一次循环n=1:初始xs长度为1,每个元素重复1次,新xs长度=1*1=1
  • 第二次循环n=2:每个元素重复2次,新xs长度=1*2=2
  • 第三次循环n=3:每个元素重复3次,新xs长度=2*3=6
    但这个假设不符合Python的实际运行规则。

核心原因

结果为27是两个Python特性共同作用的结果:

  1. 迭代器的惰性求值特性
    more_itertools.flatten返回的是迭代器对象,赋值时不会立刻执行内部的迭代逻辑,只有最后调用mo.ilen(xs)消费迭代器的时候,才会逐层触发计算。
  2. 生成器的迟绑定特性
    循环中rep(x, n) for x in xs是生成器表达式,它内部引用的变量n不会在生成器定义时就保存当前值,而是等到实际迭代的时候才会读取变量的当前值。

三次循环全部跑完后才会执行mo.ilen对迭代器求值,此时循环变量n已经停留在最后一次迭代的取值3,三层嵌套的迭代器计算时所有层的n取值都是3,最终长度计算为1 * 3 * 3 * 3 = 27,和实际运行结果一致。

修复方案

如果要得到预期的6,只需要在每次循环时强制对迭代器求值,把结果转为实体列表即可:

for n in [1, 2, 3]:
    xs = list(mo.flatten(rep(x, n) for x in xs))

这样每次循环都会用当时的n值计算出实际的元素列表,不会出现后续变量覆盖的问题。

内容的提问来源于stack exchange,提问作者psarka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 00:48:04