Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.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_Iterator - Fatal编程技术网

Python 为什么可以';我不能在同一个数据上迭代两次吗?

Python 为什么可以';我不能在同一个数据上迭代两次吗?,python,iterator,Python,Iterator,老实说,我有点困惑,为什么我不能在同一个数据上迭代两次呢 def _view(self,dbName): db = self.dictDatabases[dbName] data = db[3] for row in data: print("doing this one time") for row in data: print("doing this two times") 这将打印几次“执行此操作一次”(因为数据有几行)

老实说,我有点困惑,为什么我不能在同一个数据上迭代两次呢

def _view(self,dbName):
    db = self.dictDatabases[dbName]
    data = db[3]

    for row in data:
        print("doing this one time")

    for row in data:
        print("doing this two times")
这将打印几次“执行此操作一次”(因为数据有几行),但根本不会打印“执行此操作两次”

第一次迭代数据时效果很好,但第二次运行最后一个列表“for row in data”时,这不会返回任何结果。。。所以执行一次有效,但不是两次


仅供参考-数据是一个csv.reader对象(如果这是原因).

这是因为
数据是一个迭代器,您只能使用迭代器一次。例如:

lst = [1, 2, 3]
it = iter(lst)

next(it)
=> 1
next(it)
=> 2
next(it)
=> 3
next(it)
=> StopIteration
如果我们使用
for
循环遍历某些数据,那么最后一次
StopIteration
将导致它第一次退出。如果我们再次尝试迭代它,我们将继续得到
StopIteration
异常,因为迭代器已经被使用

现在来看第二个问题:如果我们确实需要多次遍历迭代器,该怎么办?一个简单的解决方案是创建一个包含元素的列表,我们可以根据需要多次遍历它。只要列表中的元素很少,就可以了:

data = list(db[3])
但如果有许多元素,最好使用以下方法创建独立迭代器:

现在,我们可以依次循环每一个:

for e in it1:
    print("doing this one time")

for e in it2:
    print("doing this two times")

一旦迭代器耗尽,它将不再产生任何结果

>>> it = iter([3, 1, 2])
>>> for x in it: print(x)
...
3
1
2
>>> for x in it: print(x)
...
>>>

我想为那些在2017年寻找解决方案并使用python 2.7或3的人完成@ÓscarLópez的答案

方法tee()现在不接受任何关键字参数,并等待第二个参数为整数,而不是关键字。这是使用tee()的正确方法:


Iterable vs.iterator。我并不是说这是重复的,但您可能还想参考更多上下文/解释。为什么不在数据上迭代一次,并在第一次执行所有需要的操作?相关:
it.next()
对于本例很好,因为您可以想象
next
方法正在以某种方式修改
it
,以跟踪已生成的内容(当然,对于许多对象,这种“跟踪”或计算下一个要返回的值发生在C代码中)。但是,通常在编写代码时,最好使用
next(it)
,前提是您不需要支持非常旧的python版本——这与python3.x是向前兼容的,在python3.x中
it.next()
被重命名为
it.\uuuuuuuuuuuuuuuu()
…@scarLópez——实际上我并没有暗示您应该更改答案。我确实有点喜欢
it。next()
使
it
可能正在改变的关联变得多么清晰<代码>下一步(it)
不太清晰,因为它返回一些东西,并且
会被修改(这在python中通常不是最直观的事情…@ÓscarLópez在
tee
上的文档中指出:“这个itertool可能需要大量的辅助存储(取决于需要存储多少临时数据)。一般来说,如果一个迭代器在另一个迭代器启动之前使用了大部分或全部数据,那么使用list()而不是tee()会更快。“因此,如果您像示例中那样使用
it1
it2
,您可能不会从
tee
中获得任何真正的好处(同时可能会带来一些额外的开销).I support@svk-在这种情况下,
tee
将以比单个
list
调用效率稍低的方式创建迭代器值的完整副本。人们应该使用
tee
而不是在iterable中有很多元素的情况下-这是不相关的,而是在存在使用位置的情况下-在这种情况下
tee
的缓存可以小于整个列表。例如,如果两个迭代器并驾齐驱,比如在
zip(a,islice(b,1))
调用中。这是有意义的,但我如何绕过它?@JSchwartz,将迭代器转换为序列对象(
list
tuple
)。然后迭代序列对象。(仅当csv的大小不是很大时)@JSchwartz,或者,如果您可以访问底层文件对象,并且该对象是可查找的。您可以在第二个循环之前更改文件位置:
csv\u file\u object.seek(0)
>>> it = iter([3, 1, 2])
>>> for x in it: print(x)
...
3
1
2
>>> for x in it: print(x)
...
>>>
import itertools
it1, it2 = itertools.tee(db[3], 2)