嵌套循环生成器为何未输出预期结果?
嵌套循环生成器为何未输出预期结果?
嘿,这个问题我太熟啦!咱们来一步步拆解~
首先看你尝试的代码:
tuple(map(tuple, tuple(((x,y) for x in range(5)) for y in range(3))))
你期望得到每个子元组对应不同的y值,但实际输出里所有元组的第二个元素都是2,问题出在生成器的延迟求值特性上!
生成器表达式是懒加载的——外层的for y in range(3)循环跑的时候,里面的(x,y) for x in range(5)并没有真的开始计算,它只是记住了要用到变量y。等外层循环完全结束,y已经变成了最后一个值2,这时候才开始迭代所有内层生成器,所以所有的x对应的y都是2,自然就得到了全是(x,2)的结果。
给你几个解决办法:
换成列表推导(立即求值):把内层的生成器改成列表推导,这样每次外层循环到某个
y时,会立刻把对应的(x,y)都计算并存储起来:tuple(map(tuple, tuple([(x,y) for x in range(5)] for y in range(3))))绑定当前y值:用变量重命名或者闭包,强制生成器捕获每次循环的
y值,而不是最后那个:# 简单重命名变量,避免引用同一个y tuple(map(tuple, tuple(((x, y_val) for x in range(5)) for y_val in range(3)))) # 或者用闭包明确绑定 tuple(map(tuple, tuple((lambda y=y: ((x,y) for x in range(5)))() for y in range(3))))更简洁的tuple推导写法:其实不用
map也能直接生成目标结构,可读性更高:tuple(tuple((x,y) for x in range(5)) for y in range(3))
试一下这些写法,就能得到你预期的结果啦:
(((0, 0), (1, 0), (2, 0), (3, 0), (4, 0)), ((0, 1), (1, 1), (2, 1), (3, 1), (4, 1)), ((0, 2), (1, 2), (2, 2), (3, 2), (4, 2)))
备注:内容来源于stack exchange,提问作者KLc3088
相关产品推荐
相关产品推荐

