Belajar dengan membaca secara berurutan

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.

Tiga Pola yang Dicakup Higher-Order Function
①Tetapkan fungsike variabelf = printf("HELLO")②Teruskan fungsisebagai argumenafter(2, greet)→ callback③Kembalikan fungsisebagai nilaimake_greeter("Budi")→ kembalikan fungsi
Karena fungsi adalah nilai, kamu bisa memakainya dalam tiga cara: penetapan variabel, penerusan argumen, dan nilai kembali.

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.

Nama Fungsi Hanyalah Nama yang Menunjuk ke Objek Fungsi
print(nama bawaan)objek fungsi(badan)OutputHELLOa(alias buatanmu)menunjukreferensi samaprint("HELLO")a("HELLO")
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.

Rasakan fungsi sebagai nilai, dengan fungsi buatanmu sendiri dan fungsi bawaan.

① Definisikan def greet(): dengan badan print("Halo").

② Bangun alias dengan say = greet dan panggil say() — pastikan kamu mendapat hasil yang sama dengan greet().

③ Buat alias untuk len bawaan juga dengan f = len, dan cetak hasil f("Python") dengan print(...).

(Saat jawaban benar, penjelasan akan muncul.)

Python Editor

Jalankan kode untuk melihat output

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!
Callback Berarti "Teruskan Perilaku Dalam"
Sisi pemanggilgreet_all(names, formal)Higher-order fngreet_all(names, formatter)Untuk tiap name,panggil formatter(name)Callbackformal(name)"Halo Budi, ..."3 baris outputteruskan fnbadanbisa ditukarhasil
Badan greet_all hanyalah loop; cara mengubah tiap name menjadi baris sapaan diserahkan ke argumen formatter.

Bangun higher-order function yang memungkinkan sisi pemanggil menukar format notifikasi untuk daftar nama pengguna.

① Definisikan def notify_all(users, formatter):. Dengan for user in users:, panggil print(formatter(user)) untuk tiap pengguna.

② Bangun def login_alert(name): yang mengembalikan f"[Login] {name} telah masuk".

③ Bangun def logout_alert(name): yang mengembalikan f"[Logout] {name} telah keluar".

④ Siapkan users = ["Budi", "Siti"], lalu panggil notify_all(users, login_alert) dan notify_all(users, logout_alert).

Python Editor

Jalankan kode untuk melihat output

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
Mengganti Callback Berdasarkan Kondisi
process_number(7,handle_even,handle_odd)n % 2 == 0?even_callback(n)→ handle_evenodd_callback(n)→ handle_oddputuskanTrueFalse

Bangun higher-order function yang merutekan pemrosesan pembayaran ke satu callback saat sukses dan callback lain saat gagal.

① Definisikan def process_payment(amount, on_success, on_failure):. Jika amount > 0, panggil on_success(amount); jika tidak panggil on_failure(amount).

② Bangun def notify_success(amount): yang mencetak f"Pembayaran {amount} yen selesai".

③ Bangun def notify_failure(amount): yang mencetak f"Jumlah {amount} tidak valid".

④ Panggil process_payment(1500, notify_success, notify_failure) dan process_payment(0, notify_success, notify_failure).

Python Editor

Jalankan kode untuk melihat output

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
make_logger Mengembalikan "Fungsi yang Sudah Terkonfigurasi"
Module (Global Namespace)
  • info = make_logger("INFO") — menerima fungsi yang mengingat INFO
  • error = make_logger("ERROR") — menerima fungsi terpisah yang mengingat ERROR
Frame make_logger("INFO")
  • Menyimpan prefix = "INFO"
  • return log yang didefinisikan di dalam
log (masih mengingat INFO)
  • Mencetak [INFO] ... pada setiap pemanggilan
Frame make_logger("ERROR")
  • Menyimpan prefix = "ERROR"
  • return fungsi log terpisah
log (masih mengingat ERROR)
  • Objek fungsi terpisah, independen dari info
Setiap pemanggilan make_logger membangun fungsi log terpisah yang mengingat prefix-nya dan mengembalikannya. Pemanggil memakainya dengan nama pendek seperti info() / error().

Bangun higher-order function yang mengembalikan fungsi penanda yang mengingat tag-nya.

① Definisikan def make_tagger(tag):. Di dalamnya, definisikan def tag_text(text): yang mengembalikan f"<{tag}>{text}</{tag}>".

② Di akhir, kembalikan inner function dengan return tag_text.

③ Bangun dua fungsi: b = make_tagger("b") dan i = make_tagger("i").

④ Panggil print(b("Penting")) dan print(i("Penekanan")) dan pastikan <b>Penting</b> / <i>Penekanan</i> muncul masing-masing.

Python Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Apa yang dicetak kode ini?
def greet():
print("Hi")
f = greet
f()

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")