Fungsi adalah suatu “blok” kode yang dapat dipakai ulang untuk melakukan tugas tertentu. Dengan fungsi, program jadi lebih terstruktur, mudah di-maintenance, dan menghindari duplikasi kode.
Intuisi secara matematis \(\to\) jika pembaca mengenal notasi \(( y = f(x) )\), maka fungsi di Python juga mirip, yaitu masukan → proses → keluaran. Bedanya, fungsi Python bisa menerima banyak argumen dan mengembalikan beragam tipe data.
Beberapa alasan menggunakan fungsi dalam membuat suatu program, termasuk di Python:
Perhatikan kode berikut:
def nama_fungsi(parameter1, parameter2):
# blok kode
hasil = parameter1 + parameter2
return hasil # mengembalikan nilai
# pemanggilan
jumlah = nama_fungsi(2, 3)
print(jumlah) # 5
Penjelasan:
def membuka definisi fungsi.parameter1, parameter2 adalah parameter (variabel lokal pada fungsi, bukan variabel global).return mengembalikan nilai luaran. Tanpa return, fungsi mengembalikan None alias kosong.Meskipun tidak error, fungsi tanpa return dinilai kurang berguna, karena hal ini sama saja dengan menulis kode tanpa fungsi. Misalnya kode berikut (tanpa return), sama saja dengan mencetak teks, bukannya memberikan nilai luaran dari fungsi yang sudah didefinisikan.
def sapa(nama):
print(f"Halo, {nama}!")
sapa("Mohamad Zaenudin") # mencetak teks; tidak mengembalikan nilai
Terdapat dua cara melakukan parsing argumen, yaitu berdarakan posisi dan kata kunci. Cek kode berikut.
def luas_persegi_panjang(panjang, lebar):
return panjang * lebar
print(luas_persegi_panjang(5, 2)) # posisi
print(luas_persegi_panjang(lebar=2, panjang=5)) # kata kunci
Memanggil kode dengan parsing argumen berdasarkan posisi maupun kata kunci sama baiknya, namun untuk keperluan yang memerlukan ketelitian, penggunaan kata kunci lebih umum digunakan.
Perhatikan kode berikut:
def pangkat(x, n=2):
return x ** n
print(pangkat(3)) # 9 (default n=2)
print(pangkat(3, 3)) # 27
Pada kode tersebut, kita menggunakan n sebagai input fungsi, tapi sudah memberikan nilai default.
Catatan penting: JANGAN gunakan objek mutable/ (misalnya
list,dict) sebagai default (lihat §10).
*args dan **kwargsJika kita menginginkan jumlah argumen dari fungsi yang kita buat secara fleksibel, kita bisa gunakan kode seperti contoh berikut.
def jumlahkan_semua(*args):
total = 0
for x in args:
total += x
return total
def cetak_opsi(**kwargs):
for k, v in kwargs.items():
print(k, "=", v)
print(jumlahkan_semua(1, 2, 3, 4)) # 10
cetak_opsi(warna="biru", ukuran=42) # warna = biru, ukuran = 42
returnBeberapa hal mengenai fungsi:
return untuk tipe data apa pun: angka (int, float, dsb), string, list, dict, bahkan fungsi lain.tuple). Cek kode berikut:def statistik_sederhana(data):
n = len(data)
rataan = sum(data) / n
minimum = min(data)
maksimum = max(data)
return rataan, minimum, maksimum # tuple
mean, min_, max_ = statistik_sederhana([1, 2, 6, 9])
Untuk kemudahan penggunaan di masa mendatang atau berkomunikasi dengan pengembang lainnya, sebaiknya kita memberikan penjelasan dari fungsi yang kita buat. Beberapa teknik dokumentasi dan anotasi di Python.
Perhatikan kode berikut yang diapit dengan tanda """.
def konversi_c_ke_f(c):
"""Konversi suhu dari Celcius ke Fahrenheit.
Rumus:
F = 9/5 * C + 32
"""
return 9/5 * c + 32
print(konversi_c_ke_f.__doc__)
Cek kode berikut ini. Sama-sama menggunakan """, namun hanya satu baris saja.
from typing import List, Tuple
def rangkum(data: List[float]) -> Tuple[float, float, float]:
"""Kembalikan nilai (mean, min, max)."""
mean = sum(data) / len(data)
return mean, min(data), max(data)
Catatan: Type hints tidak memaksa tipe saat runtime, tetapi sangat membantu pembacaan dan pemeriksaan secara statis.
global/nonlocalx = 10 # global
def f():
x = 5 # lokal (menutupi global di dalam fungsi)
print(x)
f() # 5
print(x) # 10
counter = 0
def tambah():
global counter
counter += 1
nonlocal (untuk nested function)def pembuat_counter():
hitung = 0
def naik():
nonlocal hitung
hitung += 1
return hitung
return naik
c = pembuat_counter()
print(c(), c(), c()) # 1 2 3
Python memperlakukan fungsi sebagai suatu objek, sehingga suatu fungsi bisa disimpan dalam variabel, dimasukkan ke list/dict, dan dikirim sebagai argumen. Perhatikan kode berikut.
def kali_dua(x): return x * 2
daftar_fungsi = [abs, kali_dua, round]
print([f(-3.7) for f in daftar_fungsi]) # [3.7, -7.4, -4]
lambda (fungsi anonim singkat)Fungsi lambda merupakan cara singkat untuk menulis persamaan yang rumit dalam satu baris. Cek kode berikut.
kuadrat = lambda x: x * x
print(kuadrat(5)) # 25
Gunakan
lambdahanya untuk fungsi yang kecil dan sederhana; untuk logika yang kompleks, lebih baik gunakandef.
map, filter, sorted, key=Beberapa fungsi tingkat tinggi di Python.
data = [1, 2, 3, 4, 5]
# map: terapkan fungsi ke setiap elemen
kuadrat = list(map(lambda x: x*x, data)) # [1,4,9,16,25]
# filter: sisakan elemen yang memenuhi kondisi
genap = list(filter(lambda x: x % 2 == 0, data)) # [2,4]
# sorted dengan kunci
kata = ["apel", "semangka", "kiwi"]
urut = sorted(kata, key=lambda s: len(s)) # ['kiwi','apel','semangka']
Fungsi yang memanggil dirinya sendiri. Namun, wajib ada base case (kondisi berhenti) untuk menghindari loop tanpa batasan.
Fungsi faktorial dengan rumus matematika berikut ini:
\[ n! = \begin{cases} 1, & n=0 \ n \cdot (n-1)!, & n>0 \end{cases}\]
Dapat kita tulis dengna kode Python seperti ini.
def faktorial(n):
if n < 0:
raise ValueError("n harus >= 0")
if n in (0, 1): # base case
return 1
return n * faktorial(n-1) # rekursi
print(faktorial(5)) # 120
Catatan: rekursi yang berulang terlalu dalam bisa memicu
RecursionError. Penggunaan iteratif kadang lebih efisien.
Contoh fungsi yang salah.
def tambah_item(item, daftar=[]): # daftar dipakai ulang antar pemanggilan!
daftar.append(item)
return daftar
print(tambah_item(1)) # [1]
print(tambah_item(2)) # [1, 2] (efek samping tak diinginkan)
Contoh fungsi yang benar.
def tambah_item(item, daftar=None):
if daftar is None:
daftar = [] # dibuat baru setiap panggilan
daftar.append(item)
return daftar
Closure adalah fungsi yang “mengingat” variabel dari lingkup (scope) luar tempat ia didefinisikan, bahkan setelah lingkup tersebut selesai dieksekusi. Artinya, ketika suatu fungsi didefinisikan di dalam fungsi lain, fungsi inner tersebut masih dapat mengakses variabel di fungsi luar—meskipun fungsi luar sudah tidak aktif lagi. Sementara itu, Decorator adalah fungsi yang menerima fungsi lain sebagai argumen, menambahkan atau mengubah perilakunya, lalu mengembalikan fungsi baru. Dengan kata lain, decorator adalah fungsi pembungkus (wrapper) yang memperluas fungsi lain tanpa mengubah isinya.
def pembuat_pangkat(n):
def pangkat(x):
return x ** n
return pangkat
kuadrat = pembuat_pangkat(2)
kubik = pembuat_pangkat(3)
print(kuadrat(4), kubik(4)) # 16 64
import time
def timeit(func):
def wrapper(*args, **kwargs):
t0 = time.perf_counter()
try:
return func(*args, **kwargs)
finally:
dt = time.perf_counter() - t0
print(f"{func.__name__} dieksekusi {dt:.6f} s")
return wrapper
@timeit
def kerja_berat(n):
return sum(i*i for i in range(n))
kerja_berat(1_000_00) # otomatis dilaporkan durasinya
Kita bisa menggunakan raise untuk menolak input tak valid & try/except untuk menangkap error. Cek kode berikut
def akar(x: float) -> float:
if x < 0:
raise ValueError("x harus >= 0")
return x ** 0.5
try:
print(akar(-4))
except ValueError as e:
print("Gagal:", e)
hitung_rata, validasi_email.def c_to_f(c: float) -> float:
"""Celcius → Fahrenheit"""
return 9/5 * c + 32
def f_to_c(f: float) -> float:
"""Fahrenheit → Celcius"""
return 5/9 * (f - 32)
def c_to_k(c: float) -> float:
"""Celcius → Kelvin"""
return c + 273.15
def k_to_c(k: float) -> float:
"""Kelvin → Celcius"""
if k < 0:
raise ValueError("Kelvin tidak bisa negatif")
return k - 273.15
print(c_to_f(25), f_to_c(77), c_to_k(0), k_to_c(300))
from typing import Iterable, Tuple
def stats(data: Iterable[float]) -> Tuple[float, float, float]:
data = list(data)
if not data:
raise ValueError("data kosong")
mean = sum(data) / len(data)
return mean, min(data), max(data)
print(stats([2, 2, 4, 6, 9]))
def bersihkan_spasi(teks: str) -> str:
return " ".join(teks.split())
def normalisasi_kalimat(teks: str) -> str:
t = bersihkan_spasi(teks.strip())
return t.capitalize()
print(normalisasi_kalimat(" ini contoh KALIMAT "))
def pilih_motor(torsi: float, kecepatan: float) -> str:
"""Sangat disederhanakan: pilih tipe motor berdasar torsi & kecepatan target."""
if torsi > 5 and kecepatan < 200:
return "Stepper/Servo torsi besar"
elif torsi <= 5 and 200 <= kecepatan <= 3000:
return "Motor DC"
else:
return "Motor AC / Servo (cek spesifikasi detail)"
print(pilih_motor(3.2, 1500))
*args, **kwargs).