Di Python, function bukanlah perintah istimewa yang berdiri di luar sistem tipe — function adalah object, sama seperti angka 42 dan string "kopi". Object function bisa disimpan ke variabel, dimasukkan ke list dan dictionary, dikirim sebagai argument, bahkan dikembalikan dari function lain. Bahasa dengan sifat ini disebut memperlakukan function sebagai first-class citizen. Status inilah yang membuat sorted(data, key=len) dan seluruh arsitektur callback di Python mungkin.
Function sebagai Nilai #
Menuliskan nama function tanpa tanda kurung menghasilkan object function itu sendiri — bukan hasil eksekusinya:
def sapa():
return "Halo!"
salam = sapa
print(salam())
print(type(sapa))Output yang Dihasilkan:
Halo!
<class 'function'>Mari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 4 (
salam = sapa): tanda kurung tidak ada, jadi yang diikat kesalamadalah object functionsapa— bukan string hasil pemanggilan. Dua nama kini mengarah ke function yang sama, seperti dua label menempel pada satu kotak. - Baris 5 (
print(salam())): tanda kurung di sinilah eksekusi terjadi. Memanggilsalam()sama persis dengan memanggilsapa(). - Baris 6 (
print(type(sapa))):type()mengonfirmasi bahwasapaadalah object dari classfunction— bukan"Halo!".
Function sebagai Argument #
Object function yang bisa dikirim sebagai argument membuka pola higher-order function: function yang menerima function lain dan menugaskannya. Perhatikan tampilkan berikut:
def teriak(teks):
return teks.upper() + "!"
def bisik(teks):
return teks.lower() + "..."
def tampilkan(teks, gaya):
print(gaya(teks))
tampilkan("Perhatian", teriak)
tampilkan("Perhatian", bisik)Output yang Dihasilkan:
PERHATIAN!
perhatian...Pemanggilan tampilkan("Perhatian", teriak) mengirim object teriak — tanpa kurung — lewat parameter gaya. Di dalam badan function, gaya(teks) kemudian memanggil object tersebut dengan tanda kurung. Function tampilkan yang sama menghasilkan dua gaya keluaran berbeda hanya dengan berganti function yang dikirim. Argument key= pada sorted() yang kita pakai di Chapter Lambda Functions bekerja persis seperti ini.
Function dalam Koleksi #
Karena function adalah object, list dan dictionary boleh berisi function. Dictionary berisi function menjadi tabel keputusan yang menggantikan rantai if-elif:
def potongan_member(harga):
return harga - 5000
def tanpa_potongan(harga):
return harga
harga_promo = {"member": potongan_member, "umum": tanpa_potongan}
print(harga_promo["member"](50000))
print(harga_promo["umum"](50000))Output yang Dihasilkan:
45000
50000Dictionary harga_promo menyimpan dua object function sebagai value. Ekspresi harga_promo["member"] menghasilkan object function potongan_member, dan tanda kurung (50000) setelahnya langsung memanggilnya. Menambah strategi baru cukup menambah satu pasangan key-value — tanpa menyentuh kode yang sudah ada.
Function sebagai Nilai Balik #
Function juga bisa mengembalikan function. Function pembuat biasanya memilih salah satu dari beberapa function internal lalu mengirimkannya ke pemanggil:
def buat_pangkat(pangkat):
def hitung(nilai):
return nilai ** pangkat
return hitung
kuadrat = buat_pangkat(2)
kubik = buat_pangkat(3)
print(kuadrat(5))
print(kubik(2))Output yang Dihasilkan:
25
8Mari kita telaah alurnya:
- Baris 5 (
return hitung):buat_pangkatmengembalikan object functionhitung— sekali lagi tanpa tanda kurung, jadi yang dikirim adalah function-nya, bukan hasil pemanggilannya. - Baris 7 (
kuadrat = buat_pangkat(2)): pangkat2tersimpan di namespace pembungkus, lalu functionhitungyang mengingat nilai tersebut dikirim keluar. Setiap pemanggilankuadrat(5)mengevaluasi5 ** 2menghasilkan25. - Baris 8 (
kubik = buat_pangkat(3)): pemanggilan kedua membuat salinan berbeda yang mengingat pangkat3— inilah closure yang kita kenal pada Chapter local, global, dan nonlocal.
Jebakan Klasik: Lupa Kurung #
Kesalahan paling umum seputar first-class function adalah mencampuradukkan object function dengan hasil pemanggilannya. Bandingkan dua baris terakhir berikut:
>>> def ambil_poin(siswa):
... return siswa[1]
...
>>> siswa = [("Budi", 85), ("Siti", 92)]
>>> sorted(siswa, key=ambil_poin)
[('Budi', 85), ('Siti', 92)]
>>> sorted(siswa, key=ambil_poin())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ambil_poin() missing 1 required positional argument: 'siswa'Baris key=ambil_poin mengirim object function untuk dipanggil oleh sorted() — inilah yang benar. Baris key=ambil_poin() mencoba mengeksekusi ambil_poin saat itu juga tanpa argument; Python mengevaluasi argument sebelum pemanggilan sorted() terjadi, dan ambil_poin() tanpa argument langsung memicu TypeError.