A.58. Python Iterable & Iterator
Pada chapter ini kita akan belajar tentang konsep sekaligus penerapan iterable dan iterator di Python.
A.58.1. Apa itu iterable?
Iteration atau iterasi adalah proses pengaksesan item-item suatu data kolektif sesuai urutannya satu-per-satu (menggunakan metode perulangan). Penerapan keyword for in
pada data string, list, atau data kolektif lainnya adalah contoh dari iterasi.
condition = "weteng luwe"
for c in condition:
print(c)
numbers = [10, 12, 32, 44]
for n in numbers:
print(n)
Di atas, variabel condition
di-iterasi menggunakan keyword for in
, variabel c
disetiap perulangan terisi dengan huruf string satu-per-satu, bergantian, mulai huruf pertama hingga terakhir.
Begitu juga dengan variabel numbers
, nilai numerik dalam list di-iterasi dengan setiap nilai ditampung variabel n
untuk kemudian di-print.
Iterable adalah object yang bisa di-iterasi, contohnya seperti tuple, list, string, dan tipe data kolektif lainnya. Sederhananya, setiap object yang bisa digunakan pada keyword for in
adalah pasti iterable.
A.58.2. Apa itu iterator?
Iterator berbeda dibanding iterable. Iterator adalah object iterable yang bisa mengingat state perulangannya. Jadi object tersebut tau informasi seperti perulangan sedang berada di indeks ke berapa, elemen berikutnya apa, dan info mengenai kapan perulangan berhenti.
Object iterable bisa dikonversi menjadi iterator, caranya dengan membungkusnya menggunakan fungsi iter()
. Contoh:
condition = "weteng luwe"
for c in iter(condition):
print(c)
numbers = [10, 12, 32, 44]
for n in iter(numbers):
print(n)
Ok, lalu apa benefitnya? apa bedanya dengan iterable biasa? Jika mengacu ke contoh di atas, tidak akan terlihat perbedaannya dimana, karena object iterable dan iterator keduanya pasti bisa digunakan pada perulangan menggunakan keyword for in
.
Agar lebih jelas, kita berkenalan dulu dengan fungsi baru bernama next()
. Fungsi ini berguna untuk mengembalikan data iterasi berikutnya. Contoh penerapannya silakan lihat kode berikut ini:
numbers = [10, 12, 32, 44]
numbers_iter = iter(numbers)
n = next(numbers_iter)
print(n) # output ➜ 10
n = next(numbers_iter)
print(n) # output ➜ 12
n = next(numbers_iter)
print(n) # output ➜ 32
n = next(numbers_iter)
print(n) # output ➜ 44
Data list numbers
dikonversi ke bentuk iterator menggunakan fungsi iter()
, kemudian digunakan sebagai argument pemanggilan fungsi next()
4 kali, hasilnya:
- Pemanggilan ke-1 mengembalikan item index ke-1, yaitu angka
10
- Pemanggilan ke-2 mengembalikan item index ke-2, yaitu angka
12
- Pemanggilan ke-3 mengembalikan item index ke-3, yaitu angka
32
- Pemanggilan ke-4 mengembalikan item index ke-4, yaitu angka
44
Dari sini terlihat bahwa object iterator benar-benar mengingat informasi state-nya. Setelah pemanggilan fungsi next()
pertama, object numbers_iter
tau bahwa item indeks ke-1 sudah diakses, dan pengaksesan berikutnya adalah indeks ke-2, dan seterusnya.
Penggunaan fungsi
next()
terhadap object iterator yang sudah terakses semua itemnya menghasilkan error. Manfaatkan keywordtry except
jika diperlukan.
A.58.3. Custom iterator
Selain menggunakan fungsi iter()
pembuatan iterator juga bisa dilakukan via custom class. Caranya dengan mendesain custom class agar memiliki 2 hal berikut:
- Custom class harus inherit class
Iterator
milik modulecollections.abc
. - Di dalam class harus ada fungsi
__next__(self)
yang otomatis dipanggil setiap kali object digunakan pada fungsinext()
.
Pada contoh berikut, disiapkan class bernama LoopReverse
dengan tugas adalah menghasilkan object iterator yang mengembalikan item data kolektif berurutan dari belakang (terbalik).
from collections.abc import Iterator
class LoopReverse(Iterator):
def __init__(self, data):
self.data = data
self.i = 0
def __next__(self):
if (self.i+1) > len(self.data):
raise StopIteration
else:
r = self.data[len(self.data)-self.i-1]
self.i = self.i + 1
return r
numbers = [23, 2, 1, 54]
for n in LoopReverse(numbers):
print(n)
# output ↓
#
# 54
# 1
# 2
# 23
Penjelasan:
- Sewaktu class dinisialisasi, instance attribute
i
disiapkan dengan nilai0
dan attributedata
berisi data yang disisipkan via argument (pada konteks ini yang dimaksud adalah data[23, 2, 1, 54]
). - Di setiap perulangan, fungsi
__next__(self)
dipanggil, ketika nilaii
masih di bawah jumlah itemdata
, maka item nomori
dari belakang dikembalikan. Selebihnya, exceptionStopIteration
di-raise untuk menandai bahwa iterasi sudah dihentikan.
Coba test juga pengaksesan item iterator via fungsi next()
. Contoh:
numbers = [23, 2, 1, 54]
numbers_iter = LoopReverse(numbers)
n = next(numbers_iter)
print(n) # output ➜ 54
n = next(numbers_iter)
print(n) # output ➜ 1
n = next(numbers_iter)
print(n) # output ➜ 2
n = next(numbers_iter)
print(n) # output ➜ 23
Selain menggunakan class Iterator
sebagai superclass, iterator custom class juga bisa dibuat dengan cukup menambahkan fungsi __iter__(self)
yang mengembalikan data self
tanpa perlu meng-inherit class Iterator
. Contoh:
class LoopReverse:
def __init__(self, data):
self.data = data
self.i = 0
def __iter__(self):
return self
def __next__(self):
if (self.i+1) > len(self.data):
raise StopIteration
else:
r = self.data[len(self.data)-self.i-1]
self.i = self.i + 1
return r
numbers = [23, 2, 1, 54]
for n in LoopReverse(numbers):
print(n)
# output ↓
#
# 54
# 1
# 2
# 23
Method __iter__(self)
harus mengembalikan object iterator yang dimana harus memiliki method __next__(self)
. Di contoh di atas, method __next__(self)
kebetulan memang posisinya satu level dengan method __iter__(self)
, oleh karena itu object self
dijadikan nilai balik.
Catatan chapter 📑
◉ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../iterable-iterator