Python イテレータを「ページ スルー」する方法を探しています。つまり、指定されたイテレータiterとpage_sizeを、一連の「ページ」として iter からアイテムを返す別のイテレータでラップしたいと考えています。各ページ自体が、最大でpage_sizeの反復を行う反復子になります。
私はitertoolsを調べましたが、最も近いものはitertools.isliceです。いくつかの点で、私が望むのはitertools.chainの反対です。一連のイテレータを 1 つのイテレータに連鎖させるのではなく、イテレータを一連の小さなイテレータに分割したいと考えています。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 回複製するのは、私には厄介に思えます。1 つのクローンは、self.iter にさらに項目があるかどうかを確認することです。私はAlex Martelli が提案した手法を使用することにしました (彼がラッピング手法について書いていることに注意してください)。2 番目のクローンは、返されるページを内部反復子 ( self.iter ) から独立できるようにすることでした。3つのクローンを作成しないようにする方法はありますか?
- それをキャッチしてから再度発生させる以外に、 StopIteration例外を処理するより良い方法はありますか? 私はそれをまったく捕まえずに泡立たせたいと思っています。
ありがとう!-レイモンド