Decorator
Bungkus fungsi dengan perilaku tambahan tanpa mengubah isinya.
Pahami konsepnya
Decorator adalah fungsi yang menerima fungsi lain, membungkusnya dengan perilaku tambahan, lalu mengembalikan versi berlapis. Bentuk @nama_decorator di atas def adalah gula sintaks untuk fungsi = decorator(fungsi).
Contoh nyata: pencatat waktu (timing), cache hasil (@lru_cache), validasi input, autentikasi. Standard library memakainya luas: @property, @staticmethod, @classmethod, @dataclass — semua decorator.
Menulis decorator sendiri: fungsi luar menerima func, fungsi dalam (wrapper) menjalankan func dengan argumen aslinya ditambah perilaku sebelum/sesudah, lalu mengembalikan wrapper. functools.wraps(func) menjaga nama dan docstring asli tetap terlihat.
Coba contoh kode
import time
import functools
def ukur_waktu(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
mulai = time.perf_counter()
hasil = func(*args, **kwargs)
durasi = time.perf_counter() - mulai
print(f"{func.__name__}: {durasi:.4f}s")
return hasil
return wrapper
@ukur_waktu
def hitung_berat(n):
return sum(range(n))
print(hitung_berat(1_000_000))@ukur_waktu membungkus hitung_berat: sebelum eksekusi catat waktu, sesudahnya cetak durasinya. fungsi asli tetap utuh — decorator menambah lapisan tanpa menyentuh isinya. *args/**kwargs meneruskan semua argumen apa pun bentuknya.
Latihan singkat
Uji: @panggil_dua_kali — f() mencetak `halo` dua kali.