Python实现无限二维数组45度旋转时生成器被重置原因求解
问题原因分析
- 生成器的惰性执行特性导致取值顺序混乱
Python 中的生成器只有在被迭代时才会执行内部逻辑返回元素,你在rotate函数中返回inner_generator实例时,并没有立刻获取元素,只有当你手动迭代生成器时才会调用next()消费原行生成器的内容。
你的测试代码中先获取了对应第一行输出的g1、对应第二行输出的g2,但优先迭代了g2,此时原第0行的生成器从未被消费过,所以g2中取原第0行的第一个元素得到的是1,而非预期的2。即便你按顺序先迭代g1再迭代g2能得到临时的正确结果,只要迭代顺序变化,结果就会出错,因为生成器只能单向前进,无法回退读取之前的元素。 - 位置对应逻辑不匹配
顺时针旋转45度的本质是:第k个输出行的元素依次为原第k行第0列、原第k-1行第1列、原第k-2行第2列……原第0行第k列。
你的实现中,原第i行生成器的第n次调用返回第n个元素,这个n等于访问过该生成器的输出行数量,和预期需要的列号k-i(k为当前输出行号)完全不匹配,无法保证取到正确位置的元素。
修复方案
你可以为每个原行生成器增加缓存,将已经取出的元素存储下来,需要时直接从缓存读取,避免重复调用next()导致取值错位,示例实现如下:
def rotate(seq): row_idx = 0 # 存储原行生成器 row_gens = [] # 缓存每个原行已经取出的元素 row_buffers = [] while True: # 新增一行原数据 new_gen = next(seq) row_gens.append(new_gen) row_buffers.append([]) # 预先生成当前输出行的所有元素 output_row = [] for i in range(row_idx, -1, -1): # 原第i行需要取第 (row_idx - i) 列的元素 target_col = row_idx - i # 缓存不足时取新元素补充 while len(row_buffers[i]) <= target_col: row_buffers[i].append(next(row_gens[i])) output_row.append(row_buffers[i][target_col]) # 返回生成器 yield (item for item in output_row) row_idx += 1
另外你测试用例中的gen_row是循环输出固定字符串的字符,并非生成无限不重复序列,测试时可根据需求调整该生成器逻辑。
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

