web-dev-qa-db-fra.com

hasNext dans les itérateurs Python?

Les itérateurs Python n'ont-ils pas une méthode hasNext?

117
Juanjo Conti

Non, il n'y a pas une telle méthode. La fin de l'itération est indiquée par une exception. Voir la documentation .

78
avakar

Il existe une alternative à StopIteration en utilisant next(iterator, default_value).

Par exemple:

>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None

Vous pouvez donc détecter pour None ou une autre valeur pré-spécifiée pour la fin de l'itérateur si vous ne souhaitez pas utiliser la méthode des exceptions.

166
Derrick Zhang

Si vous avez vraiment besoin une fonctionnalité has-next (parce que vous venez de transcrire fidèlement un algorithme d'une implémentation de référence en Java, par exemple, ou parce que vous écrivez un prototype sur lequel devra doit être facilement transcrit Java quand c'est fini), il est facile de l'obtenir avec une petite classe wrapper. Par exemple:

class hn_wrapper(object):
  def __init__(self, it):
    self.it = iter(it)
    self._hasnext = None
  def __iter__(self): return self
  def next(self):
    if self._hasnext:
      result = self._thenext
    else:
      result = next(self.it)
    self._hasnext = None
    return result
  def hasnext(self):
    if self._hasnext is None:
      try: self._thenext = next(self.it)
      except StopIteration: self._hasnext = False
      else: self._hasnext = True
    return self._hasnext

maintenant quelque chose comme

x = hn_wrapper('ciao')
while x.hasnext(): print next(x)

émet

c
i
a
o

comme demandé.

Notez que l'utilisation de next(sel.it) en tant que fonction intégrée nécessite Python 2.6 ou supérieur; Si vous utilisez une version plus ancienne de Python, utilisez plutôt self.it.next() (et de la même manière pour next(x) dans l'exemple d'utilisation). [[Vous pouvez raisonnablement penser que cette note est redondante, car Python 2.6 existe depuis plus d'un an maintenant - mais le plus souvent quand j'utilise les fonctionnalités de Python 2.6 dans une réponse, un commentateur ou un autre se sent obligé de signaler qu'ils sont 2.6 caractéristiques, j'essaie donc de prévenir de tels commentaires pour une fois ;-)]]

31
Alex Martelli

En plus de toutes les mentions de StopIteration, la boucle "pour" de Python fait simplement ce que vous voulez:

>>> it = iter("hello")
>>> for i in it:
...     print i
...
h
e
l
l
o
11
Brian Clapper

Essayez la méthode __length_hint __ () à partir de n'importe quel objet itérateur:

iter(...).__length_hint__() > 0
8
juj

hasNext se traduit quelque peu par l'exception StopIteration, par exemple:

>>> it = iter("hello")
>>> it.next()
'h'
>>> it.next()
'e'
>>> it.next()
'l'
>>> it.next()
'l'
>>> it.next()
'o'
>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
5
miku

Non. Le concept le plus similaire est très probablement une exception StopIteration.

3
James Thompson

Vous pouvez tee l'itérateur à l'aide de, itertools.tee, et rechercher StopIteration sur l'itérateur teed.

3
sykora

Je crois que python vient de next () et selon la doc, cela jette une exception s'il n'y a plus d'éléments.

http://docs.python.org/library/stdtypes.html#iterator-types

2
Charles

Le cas d'utilisation qui m'a amené à rechercher ceci est le suivant

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        try:
            x = next(fi)
        except StopIteration:
            fi = iter(f)
            x = next(fi)
        self.a[i] = x 

où hasnext () est disponible, on pourrait le faire

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        if not hasnext(fi):
            fi = iter(f) # restart
        self.a[i] = next(fi)

ce qui pour moi est plus propre. Évidemment, vous pouvez contourner les problèmes en définissant des classes d’utilité, mais vous obtenez alors une prolifération d’une vingtaine de solutions de contournement presque équivalentes, chacune avec leurs bizarreries, et si vous souhaitez réutiliser du code utilisant différentes solutions, vous devez avoir plusieurs quasi-équivalents dans votre application, ou faire le tour du code et le réécrire pour utiliser la même approche. La maxime 'fais-le une fois et fais-le bien' échoue mal.

De plus, l'itérateur lui-même doit disposer d'un contrôle interne 'hasnext' pour pouvoir vérifier s'il doit générer une exception. Cette vérification interne est ensuite masquée de sorte qu'elle doit être testée en essayant d'obtenir un élément, en interceptant l'exception et en exécutant le gestionnaire s'il est levé. C’est inutile de cacher l’OMI.

1
John Allsup

La méthode suggérée est StopIteration . Veuillez consulter l'exemple de Fibonacci à partir de tutorialspoint

#!usr/bin/python3

import sys
def fibonacci(n): #generator function
   a, b, counter = 0, 1, 0
   while True:
      if (counter > n): 
         return
      yield a
      a, b = b, a + b
      counter += 1
f = fibonacci(5) #f is iterator object

while True:
   try:
      print (next(f), end=" ")
   except StopIteration:
      sys.exit()
0
Ramin Darvishov

une bonne approche pour de telles questions/problèmes est de vérifier ce que nous avons dans le répertoire (objet/méthode/itérateur/type/classe/...)

vous verrez que dir(iterator) return __length_hint__

et iterator.__length_hint__() est positif jusqu'à la fin de l'itération.

c'est tout.

0
Sławomir Lenart