Haben Python-Iteratoren eine hasnext
Methode?
hasnext() für Python-Iteratoren?
Juanjo Conti
Derrick Zhang
Die Alternative zum Fangen StopIteration
ist zu verwenden next(iterator, default_value)
.
Zum Beispiel:
>>> a = iter('hi')
>>> print(next(a, None))
h
>>> print(next(a, None))
i
>>> print(next(a, None))
None
Auf diese Weise können Sie nachsehen None
um zu sehen, ob Sie das Ende des Iterators erreicht haben, wenn Sie es nicht auf die Ausnahmeart machen möchten.
Wenn Ihr Iterable enthalten kann None
Werte müssen Sie stattdessen einen Sentinel-Wert definieren und prüfen:
>>> sentinel = object()
>>> a = iter([None, 1, 2])
>>> elem = next(a, sentinel)
>>> if elem is sentinel:
... print('end')
...
>>>
-
Wenn Sie None als „Sentinel“ verwenden, stellen Sie am besten sicher, dass Ihr Iterator keine Nones hat. könntest du auch machen
sentinel = object()
Undnext(iterator, sentinel)
und testen mitis
.– Sam Boosalis
3. Okt. 2013 um 18:00 Uhr
-
Wenn ich @samboosalis folge, würde ich lieber die integrierte Version verwenden
unittest.mock.sentinel
Objekt, mit dem Sie ein explizites schreiben könnennext(a, sentinel.END_OF_ITERATION)
und dannif next(...) == sentinel.END_OF_ITERATION
– ClementWalter
1. Dezember 2018 um 19:40 Uhr
-
Das Problem besteht darin, dass Sie auf diese Weise auch den nächsten Wert aus dem Iterator VERBRAUCHEN. hasNext in Java verbraucht nicht den nächsten Wert.
– Alan Franzoni
17. Juli 2020 um 12:18 Uhr
Nein, eine solche Methode gibt es nicht. Das Ende der Iteration wird durch eine Ausnahme angezeigt. Siehe die Dokumentation.
-
„Es ist einfacher, um Vergebung zu bitten als um Erlaubnis.“
– Roger Pate
27. Dezember 2009 um 18:57 Uhr
-
„Es ist einfacher, um Vergebung zu bitten als um Erlaubnis.“: Die Überprüfung, ob ein Iterator ein nächstes Element hat, bedeutet nicht, um Erlaubnis zu bitten. Es gibt Situationen, in denen Sie die Existenz eines nächsten Elements testen möchten, ohne es zu verbrauchen. Ich würde die Try-Catch-Lösung akzeptieren, wenn es eine gäbe
unnext()
Methode, um das erste Element zurückzusetzen, nachdem ich durch Aufruf überprüft habe, ob es existiertnext()
.– Giorgio
24. Dezember 2012 um 20:26
-
@Giorgio, es gibt keine Möglichkeit herauszufinden, ob ein anderes Element existiert, ohne den Code auszuführen, der es generiert (Sie wissen nicht, ob der Generator ausgeführt wird).
yield
oder nicht). Es ist natürlich nicht schwierig, einen Adapter zu schreiben, der das Ergebnis speichertnext()
und sorgthas_next()
Undmove_next()
.– Avakar
24. Dezember 2012 um 21:10 Uhr
-
Die gleiche Idee könnte zur Umsetzung verwendet werden
hasNext()
Methode (zum Erzeugen, Zwischenspeichern und Zurückgeben von „true“ bei Erfolg oder von „false“ bei Fehler). Dann beideshasNext()
Undnext()
würde von einem gemeinsamen Basiswert abhängengetNext()
Methode und zwischengespeichertes Element. Ich verstehe wirklich nicht, warumnext()
sollte nicht in der Standardbibliothek enthalten sein, wenn es so einfach ist, einen Adapter zu implementieren, der dies bereitstellt.– Giorgio
24. Dezember 2012 um 21:21
-
@LarsH: Du meinst zB einen Iterator, der aus einer Datei liest, die beim Lesen geändert werden kann? Ich stimme zu, dass dies ein Problem sein kann (das sich auf alle Bibliotheksanbieter auswirkt).
next()
UndhasNext()
Methode, nicht nur eine hypothetische Python-Bibliothek). Also ja,next()
UndhasNext()
wird schwierig, wenn der Inhalt des gescannten Streams davon abhängt Wenn Elemente werden gelesen.– Giorgio
25. Januar 2013 um 6:42
Alex Martelli
Nein, aber Sie können Ihre eigene iterierbare Wrapper-Klasse implementieren, die Folgendes tut:
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
Dann können Sie es so verwenden:
x = hn_wrapper('ciao')
while x.hasnext():
print(next(x))
und es wird emittieren
c
i
a
o
-
Die Implementierung wäre etwas pythonischer
hasnext()
wienext()
also Umbenennen der Methode inhn_wrapper.__hasnext__()
und dann eine Funktion der obersten Ebene definieren, die diese Methode aufruftdef hasnext(iterable): return iterable.__hasnext__()
.– Boris Werchowski
30. April um 23:20 Uhr
Brian Clapper
Zusätzlich zu allen Erwähnungen von StopIteration
der Python for
Schleife macht, was Sie wollen:
>>> it = iter('hello')
>>> for i in it:
... print(i)
...
h
e
l
l
o
juj
Probieren Sie die Methode __length_hint__() von einem beliebigen Iteratorobjekt aus aus:
iter(...).__length_hint__() > 0
Sykora
Du kannst tee
der Iterator verwendet, itertools.tee
und prüfen Sie, ob StopIteration
auf dem Tee-Iterator.
hasNext
übersetzt in gewisser Weise die StopIteration
Ausnahme, z.B.:
>>> 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
Dokumente: http://docs.python.org/library/Exceptions.html#Exceptions.StopIteration- Ein Artikel über Iteratoren und Generatoren in Python: http://www.ibm.com/developerworks/library/l-pycon.html
Verwandt: Woher weiß ich, ob ein Generator von Anfang an leer ist?
– Benutzer2314737
5. Mai 2017 um 10:58
So etwas gibt es derzeit nicht. Und ich denke, der richtige Weg, dies zu tun, besteht darin, etwas hinzuzufügen
next
Undhas_next
Methode in Iteratoren selbst, da diese Methoden nicht unabhängig definiert werden sollten.– Shiv Krishna Jaiswal
19. Februar um 15:47 Uhr