Hari 16: Closure, Decorator & Higher-Order Function
65 min
Last updated 26 Mar 2026
Higher-Order Function
Fungsi yang menerima fungsi sebagai argumen atau mengembalikan fungsi.
def terapkan(fungsi, data):
return [fungsi(x) for x in data]
print(terapkan(str.upper, ["halo","dunia"])) # ['HALO','DUNIA']
print(terapkan(lambda x: x**2, [1,2,3,4])) # [1,4,9,16]
# Fungsi sebagai nilai
operasi = {
"tambah" : lambda a, b: a + b,
"kurang" : lambda a, b: a - b,
"kali" : lambda a, b: a * b,
}
op = "tambah"
print(operasi[op](10, 5)) # 15
Closure
Fungsi yang "mengingat" variabel dari scope luarnya, bahkan setelah fungsi luar selesai dieksekusi.
def buat_counter(mulai=0):
count = [mulai] # list agar bisa dimodifikasi
def increment(step=1):
count[0] += step
return count[0]
return increment
c1 = buat_counter()
c2 = buat_counter(10)
print(c1()) # 1
print(c1()) # 2
print(c1(5)) # 7
print(c2()) # 11 — counter terpisah
def buat_pengali(faktor):
def kali(angka):
return angka * faktor # faktor "ditangkap" dari luar
return kali
kali_dua = buat_pengali(2)
kali_lima = buat_pengali(5)
print(kali_dua(8)) # 16
print(kali_lima(8)) # 40
Decorator
Decorator membungkus fungsi dengan fungsionalitas tambahan tanpa mengubah kode aslinya.
def hitung_waktu(fungsi):
import time
def wrapper(*args, **kwargs):
mulai = time.time()
hasil = fungsi(*args, **kwargs)
selesai = time.time()
print(f"{fungsi.__name__} selesai dalam {selesai-mulai:.4f}s")
return hasil
return wrapper
@hitung_waktu
def hitung_sum(n):
return sum(range(n))
print(hitung_sum(1_000_000))
# Decorator untuk logging
def log_call(fungsi):
def wrapper(*args, **kwargs):
print(f"Memanggil {fungsi.__name__}({args}, {kwargs})")
hasil = fungsi(*args, **kwargs)
print(f"Hasil: {hasil}")
return hasil
return wrapper
@log_call
def tambah(a, b):
return a + b
tambah(3, 5)
Decorator dengan Parameter
def ulangi(n):
def decorator(fungsi):
def wrapper(*args, **kwargs):
for _ in range(n):
hasil = fungsi(*args, **kwargs)
return hasil
return wrapper
return decorator
@ulangi(3)
def sapa(nama):
print(f"Halo, {nama}!")
sapa("Budi") # mencetak 3 kali
# functools.wraps — pertahankan metadata fungsi asli
from functools import wraps
def decorator_baik(fungsi):
@wraps(fungsi)
def wrapper(*args, **kwargs):
return fungsi(*args, **kwargs)
return wrapperAssignment
Buat decorator @validasi_input yang memastikan semua argumen angka positif sebelum fungsi dijalankan. Jika ada yang negatif/nol, raise ValueError. Terapkan pada fungsi luas_persegi dan volume_kubus.
Expected output:
Luas persegi sisi 5 : 25
Volume kubus sisi 3 : 27
Error: Semua input harus positif! Dapat: -4
Error: Semua input harus positif! Dapat: 0
PY
main.py
Solution
Output