Loop for bekerja otomatis, tetapi otomasi itu kadang membatasi: kadang kita ingin mengambil tepat satu elemen, mengintip dua-dua elemen, atau membagi aliran data ke beberapa proses. Fungsi bawaan iter() dan next() membuka kendali penuh itu — sekaligus memperlihatkan secara persis apa yang terjadi di dalam mesin iterasi yang kita bahas pada Chapter Iterable dan Iterator.
Membuat Iterator dengan iter() #
Fungsi iter() menerima sebuah iterable dan mengembalikan kursor segar yang siap membaca dari elemen pertama. Setiap panggilan next() pada kursor tersebut mengambil satu elemen sekaligus memajukan posisi baca:
angka = [10, 20, 30]
iterator = iter(angka)
print(next(iterator))
print(next(iterator))
print(next(iterator))Output yang Dihasilkan:
10
20
30Bedah prosesnya baris per baris:
- Baris 2 (
iterator = iter(angka)): interpreter membuatlist_iteratorbaru dengan posisi baca menunjuk sebelum elemen pertama. - Baris 4 (
print(next(iterator))):next()mengembalikan elemen10dan memajukan posisi baca ke elemen kedua. - Baris 5-6: dua pemanggilan berikutnya mengambil
20lalu30; posisi baca kini berada di ujung list.
Satu iterable bisa memiliki lebih dari satu kursor aktif, dan setiap kursor berjalan dengan kecepatannya sendiri. Setiap panggilan iter() selalu memproduksi iterator yang independen:
buah = ["apel", "jeruk", "mangga"]
tim_a = iter(buah)
tim_b = iter(buah)
print(next(tim_a))
print(next(tim_b))
print(next(tim_a))Output yang Dihasilkan:
apel
apel
jerukKedua kursor membaca dari list yang sama, tetapi posisinya tercatat terpisah: tim_a sudah dua langkah (apel, jeruk) sementara tim_b baru satu langkah (apel). Inilah sebabnya list bisa diiterasi berulang kali — setiap for membuat kursor barunya sendiri.
Mengambil Elemen dengan next() dan StopIteration #
Apa yang terjadi jika next() dipanggil setelah data habis? Iterator tidak mengembalikan None; iterator mengangkat exception StopIteration:
>>> nomor = iter([7, 8])
>>> next(nomor)
7
>>> next(nomor)
8
>>> next(nomor)
Traceback (most recent call last):
...
StopIterationJika akhir aliran adalah kondisi normal yang kita antisipasi, next() menerima argumen kedua sebagai nilai default — nilai yang dikembalikan sebagai pengganti exception:
antrean = iter(["A001", "A002"])
print(next(antrean, "antrean kosong"))
print(next(antrean, "antrean kosong"))
print(next(antrean, "antrean kosong"))Output yang Dihasilkan:
A001
A002
antrean kosongDua pemanggilan pertama masih menemukan nomor antrean asli. Pemanggilan ketiga menemukan aliran kosong, sehingga next() mengembalikan string default "antrean kosong" tanpa exception sedikit pun.
Pola nilai default ini cocok untuk loop “tarik sampai habis”: nilai default berperan sebagai penanda bahwa aliran sudah selesai, sehingga loop while bisa berhenti dengan rapi tanpa perlu menangkap StopIteration sama sekali. Pemilihan nilai default harus hati-hati — gunakan nilai yang dipastikan tidak pernah muncul sebagai data asli, misalnya None atau string penanda khusus.
Melihat Jebakan Mutasi List dari Dekat #
Pada Chapter Iterasi Collections kita melihat bahwa menghapus elemen dari list yang sedang diiterasi membuat sebagian elemen terlewat. Sekarang, dengan kursor yang bisa kita maju manual, mekanisme loncatannya terlihat telanjang:
angka = [1, 2, 2, 3, 4]
iterator = iter(angka)
print(next(iterator))
print(next(iterator))
angka.remove(2)
print(next(iterator))
print(list(iterator))Output yang Dihasilkan:
1
2
3
[4]Mari kita lacak setiap langkahnya:
next(iterator)pertama: mengembalikan1; posisi baca berpindah ke indeks1.next(iterator)kedua: mengembalikan2pertama; posisi baca berpindah ke indeks2.angka.remove(2): list berubah menjadi[1, 2, 3, 4]— angka2yang kedua bergeser turun ke indeks1.next(iterator)ketiga: kursor membaca indeks2, yang kini berisi3. Angka2yang bergeser tidak pernah tersentuh — inilah elemen yang “lolos” saat loopformenjalankan skenario yang sama.list(iterator): sisa aliran hanya[4], menegaskan bahwa satu nilai memang terlewat selamanya.
Dengan protokol iterasi kini dikuasai penuh, dua chapter berikutnya menyediakan alat bantu bawaan yang menghidupkan pola-pola berulang: enumerate() untuk pasangan posisi-nilai dan zip() untuk perjalanan beberapa koleksi sekaligus.