Bukankah iterators Python punya hasNext
metode?
Bukankah iterators Python punya hasNext
metode?
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()
.
yield
atau 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 StopIteration
dengan 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 None
atau 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.sentinel
objek 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-next
fungsi (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_next
metode. Desain Python tidak memungkinkan untuk, katakanlah, gunakan filter
untuk memeriksa apakah array berisi elemen yang cocok dengan predikat yang diberikan. Kesombongan dan kepicikan komunitas Python sangat mengejutkan.
TypeError: iter() returned non-iterator
map
dan any
bukannya filter
, tetapi Anda bisa menggunakan SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINEL
atau melupakan SENTINEL
dan hanya menggunakan try: except
dan 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.
hasNext
agak diterjemahkan sebagai StopIteration
pengecualian, 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
StopIteration
docs: 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 hasNext
metode.
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.