Soal 1Apa cara paling ringkas untuk membangun perkalian Cartesian dari [1, 2, 3] dan [A, B]?
itertools dan functools — Toolkit Iterasi dan Komposisi Fungsi
Pelajari resep iterasi combinations/product/chain/accumulate, penguncian argumen partial, dan percepatan rekursi via memoisasi @lru_cache lewat contoh.
itertools adalah kumpulan fungsi yang membangun iterable baru dari iterable yang sudah ada (kombinasi, penggabungan, akumulasi), dan functools adalah kumpulan fungsi yang mentransformasi fungsi itu sendiri (binding argumen, memoisasi). Keduanya bisa menggantikan pola for loop + pelacakan state dalam satu baris, mengecilkan kode kamu secara dramatis.
Iterable — nilai yang bisa kamu loop
Sebagian besar fungsi itertools menerima "iterable" sebagai input dan mengembalikan iterable baru, jadi penting untuk memastikan dulu apa itu iterable. Iterable (yang bisa kamu tulis di sebelah kanan for x in ___:) adalah apa pun yang bisa kamu teruskan ke for loop, list(...), sum(...), atau map(...). list / tuple / str / dict / set / range, plus generator yang kamu tulis sendiri (fungsi memakai yield), semuanya berperilaku sebagai iterable di Python.
list / tuple / str / dict / set / range adalah iterable, begitu juga generator kustom yang dibangun dengan yield.itertools — toolkit kombinasi dan iterasi
itertools adalah modul yang mengumpulkan fungsi-fungsi yang membangun iterable baru dari yang sudah ada. Empat yang paling sering kamu pakai adalah combinations (kombinasi tanpa urutan), product (perkalian Cartesian atas beberapa set), chain (gabungkan iterable jadi satu), dan accumulate (running total atau running product). Mengetahui keempat ini memungkinkan kamu menulis ulang double for loop dan loop dengan pelacakan state jauh lebih bersih.
list(...) untuk materialisasi.| Fungsi | Input → Output | Contoh |
|---|---|---|
| combinations(it, k) | Kombinasi k elemen (tanpa urutan) | [A,B,C] → (A,B), (A,C), (B,C) |
| permutations(it, k) | Permutasi k elemen (berurutan) | [A,B] → (A,B), (B,A) |
| product(*its) | Perkalian Cartesian lintas set | [S,M] × [red,blue] → 4 kombo |
| chain(*its) | Gabungkan beberapa iterable | [1,2] + [3,4] → [1,2,3,4] |
| accumulate(it) | Akumulasi dari kiri (sum default) | [10,20,30] → [10, 30, 60] |
functools.partial — kunci argumen lebih awal
functools.partial membangun fungsi baru dengan beberapa argumen sudah dikunci. Ketika kamu perlu meneruskan fungsi dengan argumen yang terikat ke callback atau higher-order function, ini menyelamatkan kamu dari menulis fungsi wrapper satu baris seperti def wrapper(...): .... Di mana pun kamu memanggil fungsi yang sama berulang kali dengan variasi argumen kecil, partial memotong noise wrapper dan membuat kode lebih mudah dibaca.
from functools import partial
def format_with_unit(price, unit):
return f"{price}{unit}"
# Bangun fungsi baru dengan unit "USD" sudah terikat
to_usd = partial(format_with_unit, unit="USD")
# Terapkan ke harga individual — sekarang hanya price yang perlu diteruskan
print(to_usd(100)) # 100USD
print(to_usd(200)) # 200USD
print(to_usd(300)) # 300USD
exp=2 pada power(base, exp) dan kamu mendapatkan fungsi square yang hanya butuh base.functools.lru_cache — cache hasil dengan memoisasi
"Saya ingin memakai ulang hasil fungsi mahal yang dipanggil berulang dengan argumen yang sama" — muncul kapan pun output fungsi ditentukan oleh inputnya dan kecepatan penting. Membangunnya sendiri berarti mengelola cache dict sendiri, tetapi @lru_cache melakukannya dalam satu baris decorator.
@lru_cache adalah decorator yang men-cache nilai kembali fungsi. Ketika dipanggil lagi dengan argumen yang sama, ia mengembalikan nilai yang di-cache langsung, melewati perhitungan ulang. LRU (Least Recently Used — membuang entri yang tidak dipakai paling lama) membuang entri cache lama sehingga kamu bisa membatasi penggunaan memori dengan sesuatu seperti maxsize=128.
Jangan tambahkan ke fungsi dengan side effect
@lru_cache mengasumsikan "argumen yang sama → nilai kembali yang sama". Terapkan ke fungsi dengan side effect (membaca file / menulis ke DB / mengembalikan waktu sekarang) atau yang hasilnya bervariasi untuk input yang sama, dan kamu akan mendapat bug di mana hasil pertama terus kembali selamanya. Terapkan hanya pada fungsi murni (input sama → output sama, tanpa side effect).
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Apa yang dikembalikan partial(f, x=10)?
Soal 3Mengapa @lru_cache mempercepat Fibonacci rekursif naif?