Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-迭代一个生成器表达式是否会影响迭代另一个生成器表达式的顺序?_Python_Nlp_Iterator_Generator - Fatal编程技术网

Python-迭代一个生成器表达式是否会影响迭代另一个生成器表达式的顺序?

Python-迭代一个生成器表达式是否会影响迭代另一个生成器表达式的顺序?,python,nlp,iterator,generator,Python,Nlp,Iterator,Generator,我使用两个不同的for循环迭代两个不同的生成器。但是我可以看到,通过一个生成器表达式的迭代正在影响另一个生成器表达式的迭代顺序 虽然我理解并希望这是不可能的,但不确定为什么我会经历这种奇怪的行为 we=KeyedVectors.load_word2vec_format('../input/nlpword2vecembeddingspretrained/GoogleNews-vectors-negative300.bin', binary='True') data1=(['this','is'

我使用两个不同的for循环迭代两个不同的生成器。但是我可以看到,通过一个生成器表达式的迭代正在影响另一个生成器表达式的迭代顺序

虽然我理解并希望这是不可能的,但不确定为什么我会经历这种奇怪的行为

we=KeyedVectors.load_word2vec_format('../input/nlpword2vecembeddingspretrained/GoogleNews-vectors-negative300.bin', binary='True')


data1=(['this','is','an','example','text1'],['this','is','an','example','text2'],....)

data2=(['test data1','test data2'],['test data3','test data4'],....)

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)

for i in txt_emb:
    print(i)
    break
for j in phr_emb:
    print(j)
    break
txt\u emb:

([-0.06002714 0.00999211 0.0358354…],…[0.07940271-0.02072765-0.03981323…])

phr\u emb:

([数组([-0.13269043,0.03266907,…]),数组([0.04994202,0.15716553,…])

[阵列([-0.06970215,0.01029968,…]),阵列([0.02503967,0.13970947,…]),….)

这里txt_emb是一个生成器表达式,每个iterable都是一个列表

phr_emb是一个生成器表达式,每个iterable都是一个列表,每个列表包含不同数量的数组(比如2-6)

当我像上面的代码一样首先迭代txt_emb时,我得到了txt_emb的第一个元素(索引0处的列表),这与预期的一样。类似地,当我迭代phr_emb时,我希望得到第一个元素(索引0处的列表),但我得到第二个元素(索引1处的列表)

类似地,如果我继续再次迭代txt_emb,我会得到第三个元素(索引2处的列表),而不是txt_emb索引1处的元素,因为在此之前我只迭代了txt_emb一次

当我压缩两个生成器表达式txt_emb和phr_emb并尝试迭代时,我会遇到类似的问题


我在kaggle笔记本中运行所有这些。但是如果我在笔记本的不同单元格中分别迭代这两个生成器表达式,那么我将按预期顺序获得元素。

从您的评论中,这似乎是您的两个生成器表达式从其他共享迭代器中提取数据的问题(可能是另一个生成器表达式)。当第一个生成器表达式前进时,它从第三个迭代器获取数据,这使得第二个生成器表达式无法使用该数据

您可以使用以下更简单的代码重新创建此问题:

data = range(10) # our underlying data
data_iterator = iter(data) # our shared iterator, which could be a generator expression

doubles = (x * 2 for x in data_iterator) # first generator expression
squares = (x * x for x in data_iterator) # second generator expression

print(next(doubles), next(doubles), next(doubles)) # prints 0 2 4
print(next(squares), next(squares), next(squares)) # prints 9 16 25, not 0 1 4 as you might expect
如果从一个生成器表达式中获取一些值,则另一个表达式中将跳过相应的值。这是因为它们都在后台推进共享的
数据迭代器
,该迭代器只对列表中的每个值进行一次检查

解决方案是为每个生成器创建单独的迭代器(例如,
data\u iterator
的多个版本),或者如果重新计算比较麻烦或耗时,则将其转储到类似列表的序列中,以便可以重复迭代

例如,我们可以像这样将
数据迭代器
转储到
数据列表
,然后从列表中构建生成器表达式:

data = range(10)
data_iterator = iter(data)
data_list = list(data_iterator)    # this can be iterated upon repeatedly

doubles = (x * 2 for x in data_list)
squares = (x * x for x in data_list)

print(next(doubles), next(doubles), next(doubles)) # prints 0 2 4
print(next(squares), next(squares), next(squares)) # prints 0 1 4 as expected
现在,将数据存储在这样的列表中可能需要比您想要的更多的内存。生成器和生成器表达式的一个优点是它们允许延迟计算。如果您希望保持这种延迟计算方法,并且只需要在一个生成器之前为另一个生成器提供几个值,因为它们是c如果主要是并行使用(例如,通过
zip
),则
itertools.tee
可能正是您所需要的

import itertools

data = range(10)
data_iterator = iter(data)
data_it1, data_it2 = itertools.tee(data_iterator) # two iterators that will yield the same results

doubles = (x * 2 for x in data_it1)
squares = (x * x for x in data_it2)

for d, s in zip(doubles, squares):  # consume the values in parallel
    print(d, s)

如果您计划在启动另一个生成器之前完全使用一个生成器,则仍然可以使用
tee
返回的迭代器,但在这种情况下,它们的效率要低得多(只需将整个中间迭代器转储到列表中可能更好).

据我所知,您的代码中没有生成器。请提供一个答案。您的问题的答案完全取决于所迭代的生成器。您的两次迭代之间没有内在的联系,但生成器的实现可能以某种方式交互。@Blckknght我不是“发电机”一词的含义是什么正在此处使用。如果您的
data1
data2
序列像您在此处显示的那样是真正的静态值,那么您基于它们生成的生成器表达式似乎不太可能根据您运行循环的顺序而有所不同。可能在
we
中查找某些内容会产生某种副作用,有时?我们无法实现我猜,不过我想可能有人在你使用的NLP库中有经验。你的
dataX
变量本身都是生成器表达式吗?因为如果它们都在同一个迭代器上绘制(例如文件)这可以解释您的问题。这很有帮助…生成器表达式dataX内部有214K个列表,每个列表的长度从2到20个文本元素不等。我正在尝试将此生成器表达式转换为列表,但是生成器表达式非常大,转换为列表需要花费大量时间。是否有任何选项将有助于此转换既节省内存又节省时间。我曾尝试过类似list(dataX)的方法甚至使用池进行多处理,但仍然需要很多时间。我甚至一次都没有成功地将整个表达式转换为列表。你能帮我解释一下唯一的真正原因吗?我能想象你会遇到如此严重的性能问题(这不是荒谬的大问题)如果你在某个地方内存不足,程序开始尝试交换内存时几乎停止。或者我想如果你的代码只是在某个地方使用一些深度次优的算法,那么这可能是与惰性生成器相同的问题。但无论是哪种情况,我都不认为有一个通用的解决方案。你应该这样做问另一个问题,更详细地了解你的实际计算,也许有人可以帮助你优化它。