Python Generators: Iterasi Efisien dan Kasus Penggunaan Lanjutan
Python Generators
Temukan bagaimana generator Python menyederhanakan iterasi, mengurangi boilerplate, dan meningkatkan penggunaan memori dibandingkan iterator tradisional.
What Are Generators?
Membuat iterator kustom di Python biasanya memerlukan kelas yang mengimplementasikan __iter__() dan __next__(), mengelola status internal, dan melemparkan StopIteration saat selesai. Generator menghilangkan boilerplate ini dengan memungkinkan Anda menulis fungsi sederhana yang menghasilkan nilai satu per satu.
Singkatnya, generator adalah fungsi yang mengembalikan iterator. Tubuh fungsi dieksekusi secara malas, jeda setelah setiap yield dan melanjutkan pada panggilan berikutnya.
Create Generators in Python
Mendefinisikan generator sama sederhana dengan menulis fungsi biasa dan mengganti return dengan yield:
def my_gen():
n = 1
print('This is printed first')
yield n
n += 1
print('This is printed second')
yield n
n += 1
print('This is printed at last')
yield n
Memanggil my_gen() mengembalikan iterator yang mulai dieksekusi hanya saat next() dipanggil.
a = my_gen()
next(a) # prints first message and returns 1
next(a) # prints second message and returns 2
next(a) # prints last message and returns 3
next(a) # raises StopIteration
Variabel lokal bertahan antara yield, tetapi generator hanya dapat diiterasi sekali. Untuk memulai ulang, buat instance baru.
Karena generator adalah iterator, Anda dapat melakukan loop melalui secara langsung:
for item in my_gen():
print(item)
Common Generator Patterns
Reversing a String
def rev_str(s):
for i in range(len(s)-1, -1, -1):
yield s[i]
for char in rev_str('hello'):
print(char)
Bekerja dengan iterable apa pun (list, tuple, dll.).
Generator Expressions
Generator anonim dapat dibuat dengan kurung, mirip dengan list comprehensions:
my_list = [1, 3, 6, 10]
# List comprehension
squares_list = [x**2 for x in my_list]
# Generator expression
squares_gen = (x**2 for x in my_list)
print(squares_list)
print(squares_gen)
Generator menghasilkan nilai sesuai permintaan:
a = (x**2 for x in my_list)
print(next(a)) # 1
print(next(a)) # 9
print(next(a)) # 36
print(next(a)) # 100
next(a) # StopIteration
Generator expressions dapat diteruskan langsung ke fungsi seperti sum atau max tanpa kurung di sekitarnya.
Why Use Generators?
- Concise Implementation: Menggantikan kelas iterator yang bertele-tele dengan beberapa baris kode.
- Memory Efficiency: Menghasilkan satu item pada satu waktu, ideal untuk sekuens besar atau tak hingga.
- Infinite Streams: Merepresentasikan sumber data tanpa akhir (misalnya,
while True: yield).
- Pipeline Composition: Merantai beberapa generator untuk pemrosesan data yang bersih dan mudah dibaca.
Example: Power of Two
def pow_two_gen(max_n=0):
n = 0
while n < max_n:
yield 2 ** n
n += 1
Example: Summing Squares of Fibonacci Numbers
def fibonacci_numbers(count):
a, b = 0, 1
for _ in range(count):
a, b = b, a + b
yield a
def square(nums):
for n in nums:
yield n ** 2
print(sum(square(fibonacci_numbers(10)))) # 4895
Generator memungkinkan kode yang elegan, efisien, dan mudah dipelihara untuk berbagai skenario iterasi.