我可以在Python中重置迭代器/生成器吗?我正在使用DictReader并希望将其重置(从csv模块)到文件的开头.
Ale*_*lli 74
我看到许多回答暗示了itertools.tee,但这忽略了文档中的一个重要警告:
这个itertool可能需要大量的辅助存储(取决于需要存储多少临时数据).一般来说,如果一个迭代器使用了大部分或全部数据的另一迭代开始前,它是更快地使用
list()替代tee().
基本上,tee是专为那些情况,其中两个(或更多)一个迭代器的克隆,而"不同步的"相互,不这样做的多 -相反,他们在相同的"附近"说(一彼此背后或之前的几个项目).不适合OP的"从一开始就重做"的问题.
L = list(DictReader(...))另一方面,只要序列表可以很好地适应记忆,这是非常合适的.一个新的"迭代器从一开始"(非常轻量级和低开销)可以随时iter(L)使用,部分或全部使用而不影响新的或现有的; 其他访问模式也很容易获得.
正如几个答案正确地指出的那样,在特定情况下csv你也可以.seek(0)使用底层文件对象(一个相当特殊的情况).我不确定它是否有记录和保证,但它目前有效; 它可能值得考虑仅用于真正巨大的csv文件,其中list我推荐作为一般方法将具有太大的内存占用.
Wil*_*uck 30
如果你有一个名为'blah.csv'的csv文件看起来像
a,b,c,d
1,2,3,4
2,3,4,5
3,4,5,6
Run Code Online (Sandbox Code Playgroud)
你知道你可以打开文件进行阅读,并创建一个DictReader
blah = open('blah.csv', 'r')
reader= csv.DictReader(blah)
Run Code Online (Sandbox Code Playgroud)
然后,您将能够获得下一行reader.next(),该行应该输出
{'a':1,'b':2,'c':3,'d':4}
Run Code Online (Sandbox Code Playgroud)
再次使用它会产生
{'a':2,'b':3,'c':4,'d':5}
Run Code Online (Sandbox Code Playgroud)
但是,此时如果您使用blah.seek(0),下次打电话时reader.next()您将获得
{'a':1,'b':2,'c':3,'d':4}
Run Code Online (Sandbox Code Playgroud)
再次.
这似乎是您正在寻找的功能.我确信这种方法有一些与我不了解的技巧有关.@Brian建议简单地创建另一个DictReader.如果您是第一个阅读器在读取文件的一半时,这将无法工作,因为您的新阅读器将具有来自文件中的任何位置的意外键和值.
u0b*_*6ae 22
不.Python的迭代器协议非常简单,只提供一个方法(.next()或__next__()),而且通常没有方法来重置迭代器.
常见的模式是再次使用相同的过程创建一个新的迭代器.
如果你想"保存"一个迭代器,以便你可以回到它的开头,你也可以通过使用fork iterator itertools.tee
Ste*_*ski 11
使用上面的Alex Martelli和Wilduck所倡导的.seek(0)有一个错误,即下一次调用.next()将以{key1:key1,key2:key2的形式为您提供标题行的字典,...}.解决方法是跟随file.seek(0)调用reader.next()来删除标题行.
所以你的代码看起来像这样:
f_in = open('myfile.csv','r')
reader = csv.DictReader(f_in)
for record in reader:
if some_condition:
# reset reader to first row of data on 2nd line of file
f_in.seek(0)
reader.next()
continue
do_something(record)
Run Code Online (Sandbox Code Playgroud)
Dev*_*per 10
是的,如果你numpy.nditer用来构建你的迭代器.
>>> lst = [1,2,3,4,5]
>>> itr = numpy.nditer([lst])
>>> itr.next()
1
>>> itr.next()
2
>>> itr.finished
False
>>> itr.reset()
>>> itr.next()
1
Run Code Online (Sandbox Code Playgroud)
这可能与原始问题正交,但可以将迭代器包装在一个返回迭代器的函数中。
def get_iter():
return iterator
Run Code Online (Sandbox Code Playgroud)
要重置迭代器,只需再次调用该函数。如果该函数没有参数时,这当然是微不足道的。
在函数需要一些参数的情况下,使用 functools.partial 创建一个可以传递的闭包,而不是原始迭代器。
def get_iter(arg1, arg2):
return iterator
from functools import partial
iter_clos = partial(get_iter, a1, a2)
Run Code Online (Sandbox Code Playgroud)
这似乎避免了 tee (n 副本) 或列表 (1 副本) 需要做的缓存
| 归档时间: |
|
| 查看次数: |
78185 次 |
| 最近记录: |