Soal 1Apa yang dicetak kode ini?def greet():
print("Hi")
f = greet
f()
Higher-Order Function — Memperlakukan Fungsi sebagai Argumen dan Nilai Kembali
Pelajari higher-order function Python — perlakukan fungsi sebagai nilai, callback, dan nilai kembalian.
Pada artikel sebelumnya tentang yield, kamu sudah melihat fungsi yang menghasilkan nilai satu per satu. Kali ini kamu akan melanjutkan di sisi fungsi dan melihat higher-order function — mekanisme yang memungkinkan kamu memperlakukan fungsi itu sendiri sebagai sebuah nilai.
Ada tiga pola yang perlu diingat: menetapkannya ke variabel, meneruskannya sebagai argumen (sebuah callback), dan mengembalikannya sebagai nilai.
Apa Itu Higher-Order Function — Fungsi Juga Adalah Nilai
Di Python, fungsi adalah nilai seperti halnya integer atau string. Kamu bisa menyimpannya di dalam variabel, meneruskannya ke fungsi lain sebagai argumen, dan mengembalikannya sebagai hasil.
Fungsi yang menerima fungsi sebagai argumen, atau mengembalikan fungsi sebagai hasil, disebut higher-order function. Tidak seperti print() atau len(), yang hanya bekerja pada nilai, higher-order function merangkai potongan-potongan perilaku.
Menetapkan Fungsi ke Variabel — Fungsi Juga Nilai Berbasis Referensi
Saat kamu mendefinisikan fungsi dengan def, badan fungsi dibangun di memori dan nama fungsi menunjuk ke lokasi itu. Tetapkan dengan a = print, dan a sekarang menunjuk ke badan fungsi yang sama, sehingga a("HELLO") dan print("HELLO") melakukan hal yang persis sama.
Triknya adalah tidak menyertakan () setelah nama fungsi. Tambahkan () dan kamu memanggil fungsinya, lalu nilai kembalinya yang ditetapkan.
a = print # tanpa () — menetapkan badan fungsi itu sendiri ke a
a("HELLO") # HELLO ← sama dengan print("HELLO")
print(id(print)) # misal 4395020128
print(id(a)) # alamat yang sama muncul
# Fungsi buatanmu sendiri bekerja dengan cara yang sama
def greet():
print("Halo")
say = greet # bangun alias say
say() # Halo
Dengan atau Tanpa () Mengubah Maknanya
a = print adalah bentuk yang meneruskan fungsi, sedangkan a = print("HELLO") adalah bentuk yang memanggil fungsi dan meneruskan hasilnya. Pada kasus kedua, nilai kembali print("HELLO") (None) masuk ke a, jadi memanggil a() memunculkan TypeError: 'NoneType' object is not callable.
Meneruskan Fungsi sebagai Argumen — Callback
Penggunaan paling umum dari higher-order function adalah callback — "sebuah fungsi yang diteruskan ke fungsi lain dan dipanggil pada momen tertentu", di mana "sisi pemanggil yang menentukan perilaku sesungguhnya".
Misalnya, kamu punya rutin yang "mencetak sapaan untuk daftar tiga nama", tetapi kamu ingin menukar hanya gaya sapaan dari sisi pemanggil. Pertahankan badannya sebagai loop yang mengambil nama satu per satu, dan terima bagian formattingnya sebagai argumen fungsi — lalu sisi pemanggil bisa memakai ulang rutin itu hanya dengan mengganti template sapaan.
def greet_all(names, formatter):
for name in names:
print(formatter(name))
def formal(name):
return f"Halo {name}, terima kasih atas kesetiaannya."
def casual(name):
return f"Halo, {name}!"
greet_all(["Budi", "Siti", "Ayu"], formal)
# Halo Budi, terima kasih atas kesetiaannya.
# Halo Siti, terima kasih atas kesetiaannya.
# Halo Ayu, terima kasih atas kesetiaannya.
greet_all(["Budi", "Siti", "Ayu"], casual)
# Halo, Budi!
# Halo, Siti!
# Halo, Ayu!
greet_all hanyalah loop; cara mengubah tiap name menjadi baris sapaan diserahkan ke argumen formatter.Bercabang dengan Callback Khusus per Tujuan
Kamu tidak terbatas pada meneruskan satu callback. "Pakai fungsi ini saat sukses, fungsi itu saat gagal" adalah pasangan alami lain — di mana pun kamu ingin memilih di antara beberapa callback.
Misalnya, saat kamu ingin mengganti perilaku berdasarkan apakah suatu angka genap atau ganjil, fungsi pemutus bisa hanya melakukan percabangan if, dan menyerahkan pemrosesan sesungguhnya ke dua fungsi yang disediakan oleh sisi pemanggil.
def process_number(number, even_callback, odd_callback):
if number % 2 == 0:
even_callback(number)
else:
odd_callback(number)
def handle_even(n):
print(f"{n} adalah genap")
def handle_odd(n):
print(f"{n} adalah ganjil")
process_number(4, handle_even, handle_odd) # 4 adalah genap
process_number(7, handle_even, handle_odd) # 7 adalah ganjil
Mengembalikan Fungsi sebagai Nilai — Closure dalam Praktik
Pola higher-order function lainnya adalah "mengembalikan fungsi sebagai nilai". Mengembalikan inner function dengan return sudah dibahas di artikel closure; di sini, fokusnya adalah sudut pandang praktis dari "menyerahkan kepada pemanggil sebuah fungsi yang sudah mengingat pengaturannya".
Misalnya, saat kamu ingin memproduksi massal fungsi log yang menempelkan prefix yang sama pada setiap pemanggilan, siapkan make_logger("INFO") untuk logger INFO dan make_logger("ERROR") untuk logger ERROR — dan kode pemanggil tetap sependek info("Proses dimulai").
def make_logger(prefix):
def log(message):
print(f"[{prefix}] {message}")
return log # kembalikan fungsi itu sendiri
info = make_logger("INFO")
error = make_logger("ERROR")
info("Proses dimulai") # [INFO] Proses dimulai
error("Koneksi gagal") # [ERROR] Koneksi gagal
info("Proses selesai") # [INFO] Proses selesai
- info = make_logger("INFO") — menerima fungsi yang mengingat INFO
- error = make_logger("ERROR") — menerima fungsi terpisah yang mengingat ERROR
- Menyimpan
prefix = "INFO" returnlogyang didefinisikan di dalam
- Mencetak
[INFO] ...pada setiap pemanggilan
- Menyimpan
prefix = "ERROR" returnfungsilogterpisah
- Objek fungsi terpisah, independen dari
info
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Baris mana yang meneruskan say_hi sebagai sebuah callback?
Soal 3Apa yang dicetak info("OK") setelah kode ini berjalan?def make_logger(prefix):
def log(message):
print(f"[{prefix}] {message}")
return log
info = make_logger("INFO")