Generator di Python
Artikel ini menjelaskan tentang generator di Python.
YouTube Video
Generator di Python
Ikhtisar
Generator di Python adalah jenis iterator dan fitur yang kuat untuk melakukan proses berulang secara efisien. Mereka memungkinkan Anda menulis kode yang efisien dalam penggunaan memori saat menangani data dalam jumlah besar.
Apa itu Generator?
Generator di Python adalah fungsi khusus yang menghasilkan satu nilai setiap kali dijalankan, yang didefinisikan menggunakan kata kunci yield
. Ciri utamanya adalah dapat menghentikan eksekusi sementara dengan mempertahankan keadaan dan melanjutkan di lain waktu.
Dasar-dasar yield
yield
adalah kata kunci yang mengembalikan nilai dan menunda eksekusi fungsi pada saat yang bersamaan.
1def simple_generator():
2 yield 1
3 yield 2
4 yield 3
5
6gen = simple_generator()
7
8print(next(gen)) # 1
9print(next(gen)) # 2
10print(next(gen)) # 3
- Ketika dipanggil, fungsi ini mengembalikan objek generator yang menghasilkan nilai satu per satu.
- Jika Anda memanggil
next()
saat tidak ada nilai berikutnya, akan terjadi errorStopIteration
.
next()
dan StopIteration
1def simple_generator():
2 yield 1
3 yield 2
4 yield 3
5
6gen = simple_generator()
7
8try:
9 while True:
10 value = next(gen)
11 print(value)
12except StopIteration:
13 print("Finished")
- Dengan secara eksplisit menangani error
StopIteration
seperti ini, Anda dapat mendeteksi kapan generator telah selesai.
send(value)
send(value)
dipanggil untuk melanjutkan generator dan mengirimkan value
ke posisi ekspresi yield
. Nilai yang dikirim dapat diterima di sisi generator sebagai nilai kembali dari ekspresi yield
. Pada pemanggilan pertama, Anda tidak dapat mengirim apa pun selain None
dengan send(value)
, jadi Anda harus menggunakan next()
atau send(None)
.
1def gen():
2 x = yield 1
3 print(f"x = {x}")
4 y = yield 2
5 print(f"y = {y}")
6
7g = gen()
8print(next(g)) # -> 1 (value from yield 1)
9print(g.send(10)) # -> x = 10, 2 (value from yield 2)
10print(g.send(20)) # -> y = 20, StopIteration occurs
- Dengan
send(10)
,yield
pada generator menjadi ekspresi yang mengembalikan 10, dan 10 diberikan kex
.
throw()
Memanggil throw
akan melanjutkan generator dan memunculkan exception pada posisi yield
yang sedang dijeda. Anda dapat menangani exception di dalam generator untuk melanjutkan pemrosesan. Jika exception tidak ditangkap, maka akan diteruskan ke luar dan generator berakhir.
1def gen():
2 try:
3 yield 1
4 except ValueError as e:
5 print(f"Caught: {e}")
6 yield "recovered"
7
8g = gen()
9print(next(g)) # -> 1
10print(g.throw(ValueError("boom"))) # -> Caught: boom, "recovered"
- Dalam kode ini,
throw
dipanggil untuk menyisipkan exception ke dalam generator. Di sisi generator, exception ditangani danrecovered
dikembalikan.
close()
Memanggil close()
akan mengakhiri generator. Di dalam generator, Anda dapat melakukan pembersihan menggunakan finally
. Memanggil next()
atau send()
setelah close()
akan memunculkan error StopIteration
.
1def gen():
2 try:
3 yield 1
4 finally:
5 print("Cleaning up...")
6
7g = gen()
8print(next(g)) # -> 1
9g.close() # -> Cleaning up...
- Kode ini menunjukkan bahwa memanggil
close()
mengakhiri generator dan memicu proses pembersihan di dalamfinally
.
yield from
yield from
adalah sintaks yang digunakan untuk mendelegasikan ke subgenerator. Ini adalah cara sederhana untuk memanggil generator lain di dalam generator dan meneruskan semua nilainya ke lingkup luar.
1def sub_gen():
2 yield 1
3 yield 2
4
5def main_gen():
6 yield from sub_gen()
7 yield 3
8
9print(list(main_gen())) # -> [1, 2, 3]
- Kode ini mendelegasikan semua nilai dari subgenerator ke generator luar menggunakan
yield from
, lalu menghasilkan3
.
Hubungan dengan Iterator
Generator secara internal mengimplementasikan __iter__()
dan __next__()
, sehingga merupakan jenis iterator. Oleh karena itu, mereka sepenuhnya kompatibel dengan operasi yang dapat diiterasi seperti perulangan for
.
Integrasi dengan Perulangan for
Di Python, sebuah perulangan for
secara internal menggunakan next()
untuk mengambil nilai secara otomatis.
1def simple_generator():
2 yield 1
3 yield 2
4 yield 3
5
6for value in simple_generator():
7 print(value)
Dengan metode ini, penanganan StopIteration
juga dilakukan secara otomatis.
Membuat Generator Tak Terbatas
1def count_up(start=0):
2 while True:
3 yield start
4 start += 1
5
6counter = count_up()
7print(next(counter)) # 0
8print(next(counter)) # 1
Anda dapat membuat perulangan tak terbatas, namun harus berhati-hati saat menggunakannya.
Ekspresi Generator
Ekspresi generator, yang ditulis menggunakan tanda kurung, memungkinkan Anda mendefinisikan generator dengan sintaks yang mirip dengan list comprehension.
1# List comprehension (generates the entire list at once)
2squares_list = [x**2 for x in range(5)]
3print(squares_list)
4
5# Generator expression
6squares_gen = (x**2 for x in range(5))
7for square in squares_gen:
8 print(square)
Berbeda dengan list comprehension, ekspresi generator tidak memuat semua elemen sekaligus ke dalam memori, sehingga lebih efisien dalam penggunaan memori.
Penanganan Error pada Generator
Exception dapat terjadi di dalam generator. Dalam kasus seperti itu, Anda dapat menggunakan try-except
seperti pada kode Python biasa.
1def safe_divide_generator(numbers, divisor):
2 """Yields results of dividing numbers by a given divisor safely."""
3 for number in numbers:
4 try:
5 yield number / divisor # Attempt to divide and yield result.
6 except ZeroDivisionError:
7 yield float('inf') # Return infinity if division by zero occurs.
8
9# Example usage
10numbers = [10, 20, 30]
11gen = safe_divide_generator(numbers, 0) # Create generator with divisor as 0.
12for value in gen:
13 print(value) # Output: inf, inf, inf
Dalam contoh ini, penanganan error dilakukan dengan benar jika terjadi pembagian dengan nol.
Stack Trace dari Generator
Jika terjadi exception di dalam generator, exception tersebut akan dimunculkan saat generator dilanjutkan kembali.
1def error_generator():
2 """A generator that yields values and raises an error."""
3 yield 1
4 raise ValueError("An error occurred") # Raise a ValueError intentionally.
5 yield 2
6
7gen = error_generator()
8print(next(gen)) # Output: 1 (first value yielded)
9try:
10 print(next(gen)) # Attempt to get the next value, which raises an error
11except ValueError as e:
12 print(e) # Output: An error occurred (exception message is printed)
- Generator ini mengembalikan
1
terlebih dahulu. Error yang terjadi saat dilanjutkan kembali akan ditangkap dan ditampilkan sebagai pesan error.
Contoh Penggunaan Generator
Membaca file baris demi baris (cocok untuk file berukuran besar)
1def read_large_file(filepath):
2 with open(filepath, 'r') as f:
3 for line in f:
4 yield line.strip()
- Fungsi ini membaca file teks baris demi baris menggunakan iterator, memotong spasi di setiap baris, dan mengembalikannya sebagai generator, memungkinkan file besar diproses dengan penggunaan memori yang rendah.
Generator untuk Deret Fibonacci
1def fibonacci(limit):
2 a, b = 0, 1
3 while a < limit:
4 yield a
5 a, b = b, a + b
6
7for n in fibonacci(100):
8 print(n)
- Kode ini menggunakan generator untuk menghasilkan bilangan Fibonacci secara berurutan yang kurang dari batas atas dan menampilkannya menggunakan loop
for
.
Kasus Penggunaan
Generator juga dapat digunakan dalam skenario berikut.
- Pemrosesan berurutan file CSV atau log berukuran besar
- Paginasi API
- Memproses data streaming (misal, Kafka, perangkat IoT)
Ringkasan
Konsep | Poin Utama |
---|---|
yield |
Menunda lalu mengembalikan nilai |
Fungsi Generator | Fungsi yang berisi yield dan mengembalikan iterator saat dipanggil |
Keunggulan | Efisien dalam penggunaan memori dan ideal untuk pemrosesan data besar |
Ekspresi Generator | Memungkinkan sintaks yang ringkas seperti (x for x in iterable) |
Dengan menggunakan generator, Anda dapat memproses kumpulan data besar secara efisien sambil menghemat memori dan menjaga agar kode tetap ringkas.
Anda dapat mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Silakan periksa juga saluran YouTube kami.