12 ответов:
Я вижу много ответов, предлагая itertools.ти, но это игнорирует одно важное предупреждение в документации к ней:
этот itertool может потребовать значительного вспомогательной памяти (в зависимости от много временных данных должно быть хранящийся.) В общем, если один итератор использует большинство или все данные перед запускается другой итератор, он быстрее использовать
list()вместоtee().по сути,
teeпредназначен для тех, ситуация, когда два (или более) клона одного итератора, "выходя из синхронизации" друг с другом, не делают этого много -- а, говорят, в той же "близости" (несколько пунктов позади или впереди друг друга). Не подходит для проблемы ОП "повторить с самого начала".
L = list(DictReader(...))С другой стороны идеально подходит, до тех пор, как список диктов может удобно поместиться в памяти. Новый "итератор с самого начала" (очень легкий и с низкими накладными расходами) может быть сделан по адресу в любое время сiter(L), и использованный частично или в целом без влияния новых или существующих одних; другие картины доступа также легко доступны.как справедливо отметили несколько ответов, в конкретном случае
csvвы можете.seek(0)базовый файловый объект (довольно частный случай). Я не уверен, что это задокументировано и гарантировано, хотя в настоящее время это работает; вероятно, стоит рассмотреть только для действительно огромных файлов csv, в которыхlistЯ рекомендую как общий подход будет иметь слишком большой объем памяти.
если у вас есть csv-файл с именем 'blah.csv ' это выглядит как
a,b,c,d 1,2,3,4 2,3,4,5 3,4,5,6вы знаете, что вы можете открыть файл для чтения и создания DictReader с
blah = open('blah.csv', 'r') reader= csv.DictReader(blah)тогда, вы сможете получить следующую строку с
reader.next(), которая должна вывести{'a':1,'b':2,'c':3,'d':4}снова произведет
{'a':2,'b':3,'c':4,'d':5}однако, на данный момент, если вы используете
blah.seek(0), в следующий раз, когда вы называетеreader.next()вы получить{'a':1,'b':2,'c':3,'d':4}снова.
это, кажется, функциональность, которую вы ищете. Я уверен, что есть некоторые трюки, связанные с этим подходом, которые я не знаю, однако. @Брайан предложил просто создать еще один диктофон. Это не будет работать, если вы первый читатель на полпути через чтение файла, как ваш новый читатель будет иметь неожиданные ключи и значения из любого места в файле.
нет. Протокол итератора Python очень прост и предоставляет только один метод (
.next()или__next__()), и нет метода для сброса итератора в целом.общий шаблон заключается в том, чтобы вместо этого создать новый итератор, используя ту же процедуру снова.
Если вы хотите "сохранить" итератор, чтобы вы могли вернуться к его началу, вы также можете разветвить итератор с помощью
itertools.tee
есть ошибка в использовании .ищите(0), как это отстаивали Алекс Мартелли и Уайлдак выше, а именно, что следующий вызов .далее () даст вам словарь вашей строки заголовка в виде {key1:key1, key2:key2, ...}. Работа вокруг, чтобы следовать файл.искать(0) с помощью вызова reader.следующий() чтобы избавиться от строки заголовка.
Так что ваш код будет выглядеть примерно так:
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)
Да, если вы используете
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
хотя нет сброса итератора, модуль "itertools" из python 2.6 (и более поздних версий) имеет некоторые утилиты, которые могут помочь там. Один из них-это "тройник", который может создавать несколько копий итератора и кэшировать результаты одного из них, чтобы эти результаты использовались на копиях. Я разделю ваши цели:
>>> def printiter(n): ... for i in xrange(n): ... print "iterating value %d" % i ... yield i >>> from itertools import tee >>> a, b = tee(printiter(5), 2) >>> list(a) iterating value 0 iterating value 1 iterating value 2 iterating value 3 iterating value 4 [0, 1, 2, 3, 4] >>> list(b) [0, 1, 2, 3, 4]
это, возможно, ортогонально исходному вопросу, но можно обернуть итератор в функцию, которая возвращает итератор.
def get_iter(): return iteratorсбросить итератор просто снова вызовите функцию. Это, конечно, тривиально, если функция, когда указанная функция не принимает аргументов.
в случае, если функция требует аргументов, использовать functools.частично, чтобы создать закрытие, которое может быть передано вместо оригинала итератор.
def get_iter(arg1, arg2): return iterator from functools import partial iter_clos = partial(get_iter, a1, a2)это, кажется, чтобы избежать кэширования, что tee (n копий) или список (1 копия) нужно будет сделать
для небольших файлов, вы можете использовать
more_itertools.seekable- сторонний инструмент, который предлагает сброс iterables.демо
import csv import more_itertools as mit filename = "data/iris.csv" with open(filename, "r") as f: reader = csv.DictReader(f) iterable = mit.seekable(reader) # 1 print(next(iterable)) # 2 print(next(iterable)) print(next(iterable)) print("\nReset iterable\n--------------") iterable.seek(0) # 3 print(next(iterable)) print(next(iterable)) print(next(iterable))выход
{'Sepal width': '3.5', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '5.1', 'Species': 'Iris-setosa'} {'Sepal width': '3', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '4.9', 'Species': 'Iris-setosa'} {'Sepal width': '3.2', 'Petal width': '0.2', 'Petal length': '1.3', 'Sepal length': '4.7', 'Species': 'Iris-setosa'} Reset iterable -------------- {'Sepal width': '3.5', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '5.1', 'Species': 'Iris-setosa'} {'Sepal width': '3', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '4.9', 'Species': 'Iris-setosa'} {'Sepal width': '3.2', 'Petal width': '0.2', 'Petal length': '1.3', 'Sepal length': '4.7', 'Species': 'Iris-setosa'}здесь a
DictReaderобернут в
Для DictReader:
f = open(filename, "rb") d = csv.DictReader(f, delimiter=",") f.seek(0) d.__init__(f, delimiter=",")Для Диктатора:
f = open(filename, "rb+") d = csv.DictWriter(f, fieldnames=fields, delimiter=",") f.seek(0) f.truncate(0) d.__init__(f, fieldnames=fields, delimiter=",") d.writeheader() f.flush()
list(generator())возвращает все оставшиеся значения для генератора и эффективно сбрасывает его, если он не зациклен.
Comments