Juanjo Conti
¿Los iteradores de Python tienen un hasnext
¿método?
Derrick Zhang
La alternativa a atrapar StopIteration
es usar next(iterator, default_value)
.
Por ejemplo:
>>> a = iter('hi')
>>> print(next(a, None))
h
>>> print(next(a, None))
i
>>> print(next(a, None))
None
De esta manera puede verificar None
para ver si ha llegado al final del iterador si no desea hacerlo de forma excepcional.
Si su iterable puede contener None
valores tendrá que definir un valor centinela y verificarlo en su lugar:
>>> sentinel = object()
>>> a = iter([None, 1, 2])
>>> elem = next(a, sentinel)
>>> if elem is sentinel:
... print('end')
...
>>>
-
si usa Ninguno como “centinela”, es mejor que se asegure de que su iterador no tenga ningún Ninguno. también podrías hacer
sentinel = object()
ynext(iterator, sentinel)
y prueba conis
.– sam boosalis
03/10/2013 a las 18:00
-
siguiendo a @samboosalis, preferiría usar incorporado
unittest.mock.sentinel
objeto que le permite escribir un explícitonext(a, sentinel.END_OF_ITERATION)
y luegoif next(...) == sentinel.END_OF_ITERATION
– Clemente Walter
1 dic 2018 a las 19:40
-
El problema es que, de esta manera, también CONSUMES el siguiente valor del iterador. hasNext en Java no consume el siguiente valor.
– Alan Franzoni
17 de julio de 2020 a las 12:18
No, no existe tal método. El final de la iteración se indica mediante una excepción. Ver el documentación.
-
“Es más fácil pedir perdón que permiso”.
– Roger Paté
27 de diciembre de 2009 a las 18:57
-
“Es más fácil pedir perdón que permiso”: verificar si un iterador tiene un elemento siguiente no es pedir permiso. Hay situaciones en las que desea probar la existencia de un elemento siguiente sin consumirlo. Aceptaría la solución Try Catch si hubiera una
unnext()
método para volver a colocar el primer elemento después de haber verificado que existe llamandonext()
.– Jorge
24 de diciembre de 2012 a las 20:26
-
@Giorgio, no hay forma de saber si existe otro elemento sin ejecutar el código que lo genera (no sabe si el generador se ejecutará
yield
O no). Por supuesto, no es difícil escribir un adaptador que almacene el resultado denext()
y proporcionahas_next()
ymove_next()
.– Avakar
24 de diciembre de 2012 a las 21:10
-
La misma idea podría usarse para implementar el
hasNext()
método (para producir, almacenar en caché y devolver verdadero en caso de éxito, o devolver falso en caso de error). Entonces amboshasNext()
ynext()
dependería de un subyacente comúngetNext()
método y elemento en caché. Realmente no veo por quénext()
no debería estar en la biblioteca estándar si es tan fácil implementar un adaptador que lo proporcione.– Jorge
24 de diciembre de 2012 a las 21:21
-
@LarsH: ¿Quiere decir, por ejemplo, un iterador que lee de un archivo que se puede cambiar mientras se lee? Acepto que esto puede ser un problema (que afecta a cualquier biblioteca que proporcione
next()
yhasNext()
método, no solo una biblioteca hipotética de Python). Entonces sí,next()
yhasNext()
se vuelve complicado si el contenido de la transmisión que se analiza depende de cuando se leen los elementos.– Jorge
25 de enero de 2013 a las 6:42
alex martelli
No, pero puede implementar su propia clase contenedora iterable que lo haga:
from collections.abc import Iterator
class hn_wrapper(Iterator):
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
Entonces puedes usarlo así:
x = hn_wrapper('ciao')
while x.hasnext():
print(next(x))
y emitirá
c
i
a
o
-
Sería un poco más pitónico implementar
hasnext()
comonext()
es decir, cambiar el nombre del método ahn_wrapper.__hasnext__()
y luego definir una función de nivel superior que llame a ese métododef hasnext(iterable): return iterable.__hasnext__()
.– Boris Verjovskiy
30 abr a las 23:20
Brian Clapper
Además de todas las menciones de StopIteration
el pitón for
loop hace lo que quieres:
>>> it = iter('hello')
>>> for i in it:
... print(i)
...
h
e
l
l
o
juj
Prueba el método __length_hint__() desde cualquier objeto iterador:
iter(...).__length_hint__() > 0
sykora
Puede tee
el iterador usando, itertools.tee
y verifique StopIteration
en el iterador teed.
hasNext
algo se traduce en el StopIteration
excepción, por ejemplo:
>>> 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
documentos: http://docs.python.org/library/exceptions.html#exceptions.StopIteration- Algunos artículos sobre iteradores y generadores en python: http://www.ibm.com/developerworks/library/l-pycon.html
Relacionado: ¿Cómo sé si un generador está vacío desde el principio?
– usuario2314737
5 de mayo de 2017 a las 10:58
No hay tal cosa a partir de ahora. Y creo que la forma correcta de hacer esto es agregar
next
yhas_next
en los propios iteradores, ya que estos métodos no deben definirse de forma independiente.–Shiv Krishna Jaiswal
19 de febrero a las 3:47