Les itérateurs Python n'ont-ils pas une méthode hasNext
?
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 .
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.
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 ;-)]]
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
Essayez la méthode __length_hint __ () à partir de n'importe quel objet itérateur:
iter(...).__length_hint__() > 0
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
StopIteration
docs: http://docs.python.org/library/exceptions.html#exceptions.StopIterationNon. Le concept le plus similaire est très probablement une exception StopIteration.
Vous pouvez tee
l'itérateur à l'aide de, itertools.tee
, et rechercher StopIteration
sur l'itérateur teed.
Je crois que python vient de next () et selon la doc, cela jette une exception s'il n'y a plus d'éléments.
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.
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()
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.