Bukankah iterators Python punya hasNextmetode?
Bukankah iterators Python punya hasNextmetode?
Jawaban:
Tidak, tidak ada metode seperti itu. Akhir dari iterasi ditandai dengan pengecualian. Lihat dokumentasi .
unnext()metode untuk mengembalikan elemen pertama setelah saya memeriksa apakah ada dengan memanggil next().
yieldatau tidak). Tentu saja tidak sulit untuk menulis adaptor yang menyimpan hasil next()dan menyediakan has_next()dan move_next().
hasNext()metode (untuk menghasilkan, cache dan mengembalikan true on success, atau return false on failure). Kemudian keduanya hasNext()dan next()akan tergantung pada getNext()metode yang mendasari umum dan item di-cache. Saya benar-benar tidak mengerti mengapa next()tidak ada di perpustakaan standar jika sangat mudah untuk mengimplementasikan adaptor yang menyediakannya.
next()dan hasNext()metode pustaka , bukan hanya pustaka Python hipotetis). Jadi ya, next()dan hasNext()menjadi rumit jika konten aliran yang dipindai tergantung pada saat elemen dibaca.
Ada alternatif StopIterationdengan menggunakan next(iterator, default_value).
Untuk contoh:
>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
Jadi, Anda dapat mendeteksi Noneatau nilai yang ditentukan sebelumnya untuk akhir iterator jika Anda tidak menginginkan cara pengecualian.
sentinel = object()dan next(iterator, sentinel)dan uji dengan is.
unittest.mock.sentinelobjek bawaan yang memungkinkan Anda untuk menulis secara eksplisit next(a, sentinel.END_OF_ITERATION)dan kemudianif next(...) == sentinel.END_OF_ITERATION
Jika Anda benar-benar membutuhkan sebuah has-nextfungsi (karena Anda hanya setia menyalin sebuah algoritma dari implementasi referensi di Jawa, misalnya, atau karena Anda sedang menulis sebuah prototipe yang akan perlu untuk dapat dengan mudah ditranskripsi ke Jawa ketika itu selesai), mudah untuk dapatkan dengan kelas pembungkus kecil. Sebagai contoh:
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
sekarang sesuatu seperti
x = hn_wrapper('ciao')
while x.hasnext(): print next(x)
memancarkan
c
i
a
o
seperti yang dipersyaratkan.
Perhatikan bahwa penggunaan next(sel.it)sebagai built-in membutuhkan Python 2.6 atau lebih baik; jika Anda menggunakan versi Python yang lebih lama, gunakan self.it.next()saja (dan juga untuk next(x)penggunaan contoh). [[Anda mungkin berpikir bahwa catatan ini berlebihan, karena Python 2.6 telah ada selama lebih dari satu tahun sekarang - tetapi lebih sering daripada tidak ketika saya menggunakan fitur Python 2.6 sebagai tanggapan, beberapa komentator atau lainnya merasa berkewajiban untuk menunjukkannya. bahwa itu adalah fitur 2.6, jadi saya mencoba untuk mencegah komentar semacam itu untuk sekali ;-)]]
has_nextmetode. Desain Python tidak memungkinkan untuk, katakanlah, gunakan filteruntuk memeriksa apakah array berisi elemen yang cocok dengan predikat yang diberikan. Kesombongan dan kepicikan komunitas Python sangat mengejutkan.
TypeError: iter() returned non-iterator
mapdan anybukannya filter, tetapi Anda bisa menggunakan SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINELatau melupakan SENTINELdan hanya menggunakan try: exceptdan menangkap StopIteration.
Selain semua penyebutan StopIteration, loop Python "for" hanya melakukan apa yang Anda inginkan:
>>> it = iter("hello")
>>> for i in it:
... print i
...
h
e
l
l
o
Coba metode __length_hint __ () dari objek iterator apa pun:
iter(...).__length_hint__() > 0
__init__dan __main__? Imho, ini agak berantakan tidak peduli Anda mencoba membenarkannya.
hasNextagak diterjemahkan sebagai StopIterationpengecualian, misalnya:
>>> 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
StopIterationdocs: http://docs.python.org/library/exceptions.html#exceptions.StopIterationTidak. Konsep yang paling mirip adalah pengecualian StopIteration.
Saya percaya python hanya memiliki next () dan menurut doc, ada pengecualian adalah tidak ada elemen lagi.
Kasus penggunaan yang mengarahkan saya untuk mencari ini adalah sebagai berikut
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
di mana hasnext () tersedia, orang bisa melakukannya
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)
yang bagi saya lebih bersih. Jelas Anda dapat mengatasi masalah dengan mendefinisikan kelas utilitas, tetapi yang terjadi kemudian adalah Anda memiliki dua puluh berbagai solusi yang hampir sama dengan masing-masing dengan quirks mereka, dan jika Anda ingin menggunakan kembali kode yang menggunakan workarounds yang berbeda, Anda harus memiliki beberapa yang hampir setara dalam aplikasi tunggal Anda, atau berkeliling memilih dan menulis ulang kode untuk menggunakan pendekatan yang sama. Pepatah 'lakukan sekali dan lakukan dengan baik' gagal buruk.
Selanjutnya, iterator itu sendiri perlu memiliki pemeriksaan 'hasnext' internal untuk menjalankan untuk melihat apakah perlu memunculkan pengecualian. Pemeriksaan internal ini kemudian disembunyikan sehingga perlu diuji dengan mencoba mendapatkan item, menangkap pengecualian dan menjalankan pawang jika dilemparkan. Ini tidak perlu menyembunyikan IMO.
Cara yang disarankan adalah StopIteration . Silakan lihat contoh Fibonacci dari 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()
Cara saya memecahkan masalah saya adalah dengan menjaga jumlah objek yang diulangi sejauh ini. Saya ingin mengulangi set menggunakan panggilan ke metode contoh. Karena saya tahu panjang set, dan jumlah item yang dihitung sejauh ini, saya secara efektif punya hasNextmetode.
Versi sederhana dari kode saya:
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
Tentu saja, contohnya adalah mainan, tetapi Anda mendapatkan idenya. Ini tidak akan berfungsi dalam kasus di mana tidak ada cara untuk mendapatkan panjang iterable, seperti generator dll.