Я ищу способ «пропустить» через итератор Python. То есть, я хотел бы обернуть заданный итератор итератором и page_size с другим итератором, который бы возвращал элементы из iter в виде серии «страниц». Каждая страница сама была бы итератором до page_size итераций.Как написать пейджер для итераторов Python?
Я просмотрел itertools и ближайшую вещь, которую я видел, это itertools.islice. В некотором смысле, то, что я хотел бы, это противоположность itertools.chain - вместо объединения целых итераторов в один итератор я хотел бы разбить итератор на ряд меньших итераторов. Я ожидал найти функцию подкачки в itertools, но не смог найти ее.
Я придумал следующий класс пейджера и демонстрацию.
class pager(object):
"""
takes the iterable iter and page_size to create an iterator that "pages through" iter. That is, pager returns a series of page iterators,
each returning up to page_size items from iter.
"""
def __init__(self,iter, page_size):
self.iter = iter
self.page_size = page_size
def __iter__(self):
return self
def next(self):
# if self.iter has not been exhausted, return the next slice
# I'm using a technique from
# https://stackoverflow.com/questions/1264319/need-to-add-an-element-at-the-start-of-an-iterator-in-python
# to check for iterator completion by cloning self.iter into 3 copies:
# 1) self.iter gets advanced to the next page
# 2) peek is used to check on whether self.iter is done
# 3) iter_for_return is to create an independent page of the iterator to be used by caller of pager
self.iter, peek, iter_for_return = itertools.tee(self.iter, 3)
try:
next_v = next(peek)
except StopIteration: # catch the exception and then raise it
raise StopIteration
else:
# consume the page from the iterator so that the next page is up in the next iteration
# is there a better way to do this?
#
for i in itertools.islice(self.iter,self.page_size): pass
return itertools.islice(iter_for_return,self.page_size)
iterator_size = 10
page_size = 3
my_pager = pager(xrange(iterator_size),page_size)
# skip a page, then print out rest, and then show the first page
page1 = my_pager.next()
for page in my_pager:
for i in page:
print i
print "----"
print "skipped first page: " , list(page1)
Я ищу некоторые отзывы и следующие вопросы:
- Есть пейджер уже в itertools, который служит пейджер, что я с видом?
- Клонирование self.iter 3 раза кажется kludgy для меня. Один клон должен проверить, есть ли у self.iter больше предметов. Я решил пойти с a technique Alex Martelli suggested (понимая, что он написал wrapping technique). Второй клон состоял в том, чтобы позволить возвращенной странице быть независимой от внутреннего итератора (self.iter). Есть ли способ избежать создания 3 клонов?
- Есть ли лучший способ справиться с исключением исключений, кроме того, чтобы поймать его, а затем снова поднять его? Я искушаюсь не поймать его вообще, и пусть это пузырится.
Спасибо! -Raymond
Похожие: http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks http://stackoverflow.com/questions/1335392/iteration-over-list-slices http : //stackoverflow.com/questions/760753/iterate-over-a-python-sequence-in-multiples-of-n – jfs