Python中迭代一个生成器表达式是否会影响另一生成器的迭代顺序?
问题原因
- 核心问题是你代码中
data1和data2本身是仅支持单次遍历的迭代器/生成器对象,且大概率两个变量实际指向了同一个迭代器实例,而非可重复遍历的列表、元组这类静态序列。 - 生成器表达式
txt_emb、phr_emb是惰性求值的:定义阶段不会读取data1/data2的元素,只有实际迭代时才会从底层的迭代器中取数。如果两个生成器共享同一个底层迭代器,每次迭代任意一个生成器都会消耗迭代器的一个元素,就会出现你观察到的“迭代A会影响B的索引”现象。 - 拆分到不同单元格运行时正常,是因为每个单元格运行前你都会重新初始化
data1、data2为全新的迭代器,不存在共享消耗的问题。
解决方案
- 方案1(最稳妥):将
data1、data2转为可重复遍历的列表,一次性加载所有数据到内存,后续多次遍历不会互相影响:
# 将生成器/迭代器转为列表 data1 = list(data1) data2 = list(data2) # 再定义嵌入生成器 txt_emb = (sum([we[token] for token in doc if token in we.key_to_index])/len(doc) for doc in data1) phr_emb = ([sum([we[token] for token in phrase.split(' ') if token in we.key_to_index])/len(phrase.split(' ')) for phrase in phrases]for phrases in data2)
- 方案2(内存不足时用):如果数据量过大无法全量加载到内存,使用
itertools.tee为每个使用场景生成独立的迭代器副本,避免共享消耗:
from itertools import tee # 为data1生成2个独立的迭代器,分别给txt_emb和其他场景使用 data1_for_txt, data1_for_other = tee(data1, 2) # 为data2生成2个独立的迭代器,分别给phr_emb和其他场景使用 data2_for_phr, data2_for_other = tee(data2, 2) txt_emb = (sum([we[token] for token in doc if token in we.key_to_index])/len(doc) for doc in data1_for_txt) phr_emb = ([sum([we[token] for token in phrase.split(' ') if token in we.key_to_index])/len(phrase.split(' ')) for phrase in phrases]for phrases in data2_for_phr)
注意:tee生成的迭代器如果一个迭代速度远快于另一个,会缓存大量元素,内存占用仍会上升,数据量不大的场景优先选择转列表的方案。
内容的提问来源于stack exchange,提问作者Praveen Thenraj
相关产品推荐
相关产品推荐

