Je cherche un moyen de "parcourir" un itérateur Python. C'est-à-dire, je voudrais envelopper un itérateur donné iter et page_size avec un autre itérateur qui renverrait les éléments de iter comme une série de "pages". Chaque page serait elle-même un itérateur avec page_size itérations. J'ai regardé itertools et la chose la plus proche que j'ai vue est itertools.islice. À certains égards, ce que je voudrais, c'est le contraire de itertools.chain - au lieu de chaîner une série d'itérateurs en un seul itérateur, j'aimerais décomposer un itérateur en une série d'itérateurs plus petits. Je m'attendais à trouver une fonction de pagination dans itertools mais je ne pouvais pas en trouver une. Je suis venu avec la classe de pager et la démonstration suivantes.Comment écrire un pageur pour les itérateurs Python?
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)
Je cherche des commentaires et nous avons les questions suivantes:
- est-il un téléavertisseur déjà itertools qui sert un téléavertisseur que je donne sur?
- Clonage self.iter 3 fois me semble kludgy. Un clone est de vérifier si self.iter a plus d'éléments. J'ai décidé d'aller avec a technique Alex Martelli suggested (conscient qu'il a écrit un wrapping technique). Le second clone devait permettre à la page renvoyée d'être indépendante de l'itérateur interne (self.iter). Y a-t-il un moyen d'éviter de faire 3 clones?
- Existe-t-il une meilleure façon de gérer l'exception StopIteration à côté de l'attraper, puis de le relever de nouveau? Je suis tenté de ne pas l'attraper du tout et de le laisser bouillonner.
Merci! -Raymond
connexes: 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