Gli iteratori di Python non hanno un hasNextmetodo?
Gli iteratori di Python non hanno un hasNextmetodo?
Risposte:
No, non esiste tale metodo. La fine dell'iterazione è indicata da un'eccezione. Vedere la documentazione di .
unnext()metodo per ripristinare il primo elemento dopo aver verificato che esiste chiamando next().
yieldo meno). Naturalmente, non è difficile scrivere un adattatore che memorizzi il risultato next()e fornisca has_next()e move_next().
hasNext()metodo (per produrre, memorizzare nella cache e restituire true in caso di successo o restituire false in caso di errore). Quindi entrambi hasNext()e next()dipenderebbero da un getNext()metodo sottostante comune e dall'elemento memorizzato nella cache. Davvero non vedo perché next()non dovrebbe essere nella libreria standard se è così facile implementare un adattatore che lo fornisce.
next()e hasNext()metodo della libreria , non solo su un'ipotetica libreria Python). Quindi sì, next()e hasNext()diventa difficile se il contenuto del torrente che si deve acquisire dipende da quando gli elementi vengono letti.
C'è un'alternativa al StopIterationusando next(iterator, default_value).
Per esempio:
>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
Quindi è possibile rilevare per Noneo altro valore predefinito per la fine dell'iteratore se non si desidera il modo dell'eccezione.
sentinel = object()e next(iterator, sentinel)e test con is.
unittest.mock.sentineloggetto incorporato che ti permette di scrivere un esplicito next(a, sentinel.END_OF_ITERATION)e poiif next(...) == sentinel.END_OF_ITERATION
Se davvero bisogno di una has-nextfunzionalità (perché si sta appena fedelmente trascrivere un algoritmo da un'implementazione di riferimento in Java, per esempio, o perché si sta scrivendo un prototipo che volontà essere facilmente trascritto su Java al termine), è facile ottenerlo con una piccola classe wrapper. Per esempio:
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
ora qualcosa del genere
x = hn_wrapper('ciao')
while x.hasnext(): print next(x)
emette
c
i
a
o
come richiesto.
Si noti che l'uso di next(sel.it)come built-in richiede Python 2.6 o superiore; se stai usando una versione precedente di Python, usa self.it.next()invece (e in modo simile per next(x)l'utilizzo nell'esempio). [[Potresti ragionevolmente pensare che questa nota sia ridondante, poiché Python 2.6 è in circolazione da oltre un anno ormai - ma il più delle volte quando uso le funzionalità di Python 2.6 in una risposta, alcuni commentatori o altri si sentono obbligati a sottolineare che sono caratteristiche 2.6, quindi sto provando a prevenire tali commenti per una volta ;-)]]
has_nextmetodo. Il design di Python rende impossibile, diciamo, usare filterper verificare se un array contiene un elemento che corrisponde a un dato predicato. L'arroganza e la miopia della comunità Python è sbalorditiva.
TypeError: iter() returned non-iterator
mape anyinvece di filter, ma si può usare SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINELo dimenticare un SENTINELe semplicemente usare try: excepte catturare il StopIteration.
Oltre a tutte le menzioni di StopIteration, il ciclo "for" di Python fa semplicemente quello che vuoi:
>>> it = iter("hello")
>>> for i in it:
... print i
...
h
e
l
l
o
Prova il metodo __length_hint __ () da qualsiasi oggetto iteratore:
iter(...).__length_hint__() > 0
__init__e __main__? Imho, è un po 'un casino, non importa che tu provi a giustificarlo.
hasNextsi traduce in qualche modo StopIterationnell'eccezione, ad esempio:
>>> 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
StopIterationdocumenti: http://docs.python.org/library/exceptions.html#exceptions.StopIterationNo. Il concetto più simile è probabilmente un'eccezione StopIteration.
Credo che Python abbia solo next () e secondo il documento, genera un'eccezione se non ci sono più elementi.
Il caso d'uso che mi ha portato a cercare questo è il seguente
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
dove hasnext () è disponibile, si potrebbe fare
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)
che per me è più pulito. Ovviamente è possibile aggirare i problemi definendo le classi di utilità, ma ciò che accade è una proliferazione di venti soluzioni dispari quasi equivalenti diverse ognuna con le proprie stranezze e se si desidera riutilizzare il codice che utilizza soluzioni alternative diverse, è necessario avere più equivalenti quasi nella tua singola applicazione, o andare in giro a cercare e riscrivere il codice per usare lo stesso approccio. La massima "fallo una volta e fallo bene" fallisce male.
Inoltre, lo stesso iteratore deve avere un controllo 'hasnext' interno per essere eseguito per vedere se deve sollevare un'eccezione. Questo controllo interno viene quindi nascosto in modo che debba essere testato tentando di ottenere un elemento, rilevando l'eccezione ed eseguendo il gestore se lanciato. Questo non è necessario nascondere l'IMO.
Il modo suggerito è StopIteration . Vedi l'esempio di Fibonacci da 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()
Il modo in cui ho risolto il mio problema è quello di mantenere il conteggio del numero di oggetti ripetuti fino ad ora. Volevo scorrere su un set usando le chiamate a un metodo di istanza. Dato che conoscevo la lunghezza del set e il numero di elementi contati finora, ne ho effettivamente avuto unohasNext metodo.
Una versione semplice del mio codice:
class Iterator:
# s is a string, say
def __init__(self, s):
self.s = set(list(s))
self.done = False
self.iter = iter(s)
self.charCount = 0
def next(self):
if self.done:
return None
self.char = next(self.iter)
self.charCount += 1
self.done = (self.charCount < len(self.s))
return self.char
def hasMore(self):
return not self.done
Ovviamente, l'esempio è un giocattolo, ma hai l'idea. Questo non funzionerà nei casi in cui non c'è modo di ottenere la lunghezza dell'iterabile, come un generatore ecc.