Czy iteratory Pythona nie mają hasNextmetody?
Czy iteratory Pythona nie mają hasNextmetody?
Odpowiedzi:
Nie, nie ma takiej metody. Koniec iteracji jest oznaczony wyjątkiem. Zobacz dokumentację .
unnext()metoda umieszczania pierwszego elementu z powrotem po sprawdzeniu, czy istnieje przez wywołanie next().
yieldczy nie). Oczywiście nie jest trudno napisać adapter, który przechowuje wyniki next()i zapewnia has_next()i move_next().
hasNext()metody (do tworzenia, buforowania i zwracania wartości true w przypadku sukcesu lub zwracania fałszu w przypadku niepowodzenia). Wtedy oba hasNext()i next()będą zależeć od wspólnej getNext()metody bazowej i elementu w pamięci podręcznej. Naprawdę nie rozumiem, dlaczego next()nie miałoby być w bibliotece standardowej, skoro tak łatwo jest zaimplementować adapter, który to zapewnia.
next()i hasNext()metody, a nie tylko hipotetycznej biblioteki Pythona). Więc tak, next()i hasNext()staje się trudne, jeśli zawartość skanowanego strumienia zależy od tego, kiedy elementy są odczytywane.
Istnieje alternatywa dla StopIterationużywania next(iterator, default_value).
Na przykład:
>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
Możesz więc wykryć dla Nonelub inną wstępnie określoną wartość na końcu iteratora, jeśli nie chcesz korzystać z wyjątku.
sentinel = object()i next(iterator, sentinel)oraz test z is.
unittest.mock.sentinelobiektu, który pozwala na napisanie wyraźnego, next(a, sentinel.END_OF_ITERATION)a następnieif next(...) == sentinel.END_OF_ITERATION
Jeśli naprawdę potrzebujesz do has-nextfunkcjonalności (bo jesteś po prostu wiernie transkrypcji algorytm od implementacji referencyjnej w Javie, powiedzmy, albo dlatego piszesz prototyp, że będzie potrzeba być łatwo przepisywane na Javie, kiedy jest gotowy), to łatwo zdobądź go z małą klasą wrapper. Na przykład:
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
teraz coś w stylu
x = hn_wrapper('ciao')
while x.hasnext(): print next(x)
emituje
c
i
a
o
jako wymagane.
Zwróć uwagę, że użycie programu next(sel.it)jako wbudowanego wymaga Pythona 2.6 lub nowszego; jeśli używasz starszej wersji Pythona, użyj self.it.next()zamiast tego (i podobnie next(x)w przykładzie użycia). [[Możesz rozsądnie pomyśleć, że ta uwaga jest zbędna, ponieważ Python 2.6 istnieje już od ponad roku - ale częściej niż nie, kiedy używam funkcji Pythona 2.6 w odpowiedzi, jakiś komentator lub inny czuje się zobowiązany do wskazania że są cechami 2.6, więc chociaż raz staram się uprzedzić takie komentarze ;-)]]
has_nextmetodę. Konstrukcja Pythona uniemożliwia, powiedzmy, użycie filterdo sprawdzenia, czy tablica zawiera element pasujący do danego predykatu. Arogancja i krótkowzroczność społeczności Pythona jest oszałamiająca.
TypeError: iter() returned non-iterator
mapi anyzamiast filter, ale możesz użyć SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINELlub zapomnieć a SENTINELi po prostu użyć try: excepti złapać StopIteration.
Oprócz wszystkich wzmianek o StopIteration, pętla „for” w Pythonie po prostu robi to, co chcesz:
>>> it = iter("hello")
>>> for i in it:
... print i
...
h
e
l
l
o
Wypróbuj metodę __length_hint __ () z dowolnego obiektu iteratora:
iter(...).__length_hint__() > 0
__init__i __main__? Imho, to trochę bałaganu, bez względu na to, czy próbujesz to usprawiedliwić.
hasNextco nieco przekłada się na StopIterationwyjątek, np .:
>>> 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
StopIterationdokumenty: http://docs.python.org/library/exceptions.html#exceptions.StopIterationNie. Najbardziej podobną koncepcją jest najprawdopodobniej wyjątek StopIteration.
Uważam, że python ma po prostu next () i zgodnie z dokumentem zgłasza wyjątek, że nie ma więcej elementów.
Przykład użycia, który doprowadził mnie do wyszukiwania tego, jest następujący
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
gdzie jest dostępna funkcja hasnext (), można to zrobić
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)
który dla mnie jest czystszy. Oczywiście możesz obejść problemy, definiując klasy narzędzi, ale co się wtedy dzieje, to mnożenie się dwudziestu różnych, prawie równoważnych obejść, z których każdy ma ich dziwactwa, a jeśli chcesz ponownie użyć kodu, który używa innych obejść, musisz albo mieć wiele zbliżonych do odpowiedników w jednej aplikacji lub przejść dookoła, wybierając i przepisując kod, aby zastosować to samo podejście. Zasada „zrób to raz i zrób to dobrze” kończy się niepowodzeniem.
Ponadto sam iterator musi mieć wewnętrzną kontrolę „hasnext”, aby sprawdzić, czy musi zgłosić wyjątek. To wewnętrzne sprawdzenie jest następnie ukrywane, więc należy je przetestować, próbując pobrać element, przechwytując wyjątek i uruchamiając procedurę obsługi, jeśli zostanie rzucona. To niepotrzebne ukrywanie IMO.
Sugerowanym sposobem jest zatrzymanie . Zobacz przykład Fibonacciego z 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()
Sposób, w jaki rozwiązałem ten problem, to jak dotąd zliczanie iterowanych obiektów. Chciałem iterować zestaw przy użyciu wywołań metody instancji. Ponieważ znałem długość zestawu i liczbę policzonych dotychczas elementów, skutecznie miałem hasNextmetodę.
Prosta wersja mojego kodu:
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
Oczywiście przykład jest zabawkowy, ale masz pomysł. To nie zadziała w przypadkach, gdy nie ma możliwości uzyskania długości iterowalnej, jak generator itp.