Ответ 1
Используйте itertools.islice
:
list(itertools.islice(it, n))
Я сделал генератор для чтения файла словом, и он работает хорошо.
def word_reader(file):
for line in open(file):
for p in line.split():
yield p
reader = word_reader('txtfile')
next(reader)
Каков самый простой способ получить n следующих значений в списке?
Используйте itertools.islice
:
list(itertools.islice(it, n))
EDIT: используйте itertools.islice
. Образец ниже, который я изначально предложил, - плохая идея - он падает, когда it
дает меньше n
значений, и это поведение зависит от тонких проблем, поэтому люди, читающие такой код, вряд ли поймут его точную семантику.
Есть также
[next(it) for _ in range(n)]
которые могут (?) быть более ясными для людей, не знакомых с itertools; но если вы много разбираетесь с итераторами, itertools - достойное дополнение к вашему набору инструментов.
next(it)
был исчерпан и вызывает StopIteration
? (т.е. когда у it
было меньше n
значений)
Когда я написал вышеприведенную строку пару лет назад, я, вероятно, думал, что StopIteration
будет иметь умный побочный эффект, чтобы чисто прекратить понимание списка. Но нет, все понимание StopIteration
крах, проходя мимо StopIteration
вверх. (Он выйдет чисто, только если исключение возникло из итератора range(n)
.)
Скорее всего, это не то поведение, которое вы хотите.
Но становится все хуже. Следующее должно быть эквивалентно пониманию списка (особенно на Python 3):
list(next(it) for _ in range(n))
Это не так. Внутренняя часть является сокращением для функции генератора; list()
знает, что это сделано, когда он StopIteration
где угодно.
=> Эта версия безопасно справляется, когда нет n
значений и возвращает более короткий список. (Как itertools.islice()
.)
Но это тоже изменится! Тот факт, что генератор молча выходит, когда какой-либо код внутри него вызывает StopIteration
является известной бородавкой, адресованной PEP 479. От Python 3.7 (или 3.5 с будущим импортом), который приведет к RuntimeError
вместо RuntimeError
обработки генератора. Т.е. он станет похож на поведение понимания списка. (Проверено на недавней сборке HEAD)
for word, i in zip(word_reader(file), xrange(n)):
...
Чтобы получить первые n значений генератора, вы можете использовать more_itertools.take.
Если вы планируете перебирать слова в кусках (например, 100 за раз), вы можете использовать more_itertools.chunked(https://more-itertools.readthedocs.io/en/latest/api.html):
import more_itertools
for words in more_itertools.chunked(reader, n=100):
# process 100 words