Sejauh ini kita sudah bisa membuat program yang berjalan lurus dan bercabang. Tapi program nyata butuh lebih dari itu — kita perlu memecah masalah besar menjadi potongan-potongan kecil yang bisa dipakai ulang, dan menyimpan koleksi data secara efisien. Artikel ini merangkum Lecture 7–11 dan 14 dari MIT 6.100L: fungsi, scope, lambda, tuple, list, dan dictionary.
Daftar Isi
- Fungsi: Decomposition dan Abstraction
- Scope dan Environment
- Fungsi sebagai Objek
- Lambda Function
- Keyword dan Default Arguments
- Tuple
- List dan Mutabilitas
- Aliasing dan Cloning
- Dictionary
Fungsi: Decomposition dan Abstraction
Fungsi adalah cara kita membungkus logika supaya bisa dipanggil berkali-kali tanpa menulis ulang.
def hitung_luas_lingkaran(jari_jari): """Menghitung luas lingkaran dari jari-jari yang diberikan.""" pi = 3.14159 return pi * jari_jari ** 2
# Pakai berkali-kaliprint(hitung_luas_lingkaran(5)) # 78.53975print(hitung_luas_lingkaran(10)) # 314.159Anatomi Fungsi
def nama_fungsi(param1, param2): """Docstring — jelaskan apa yang dilakukan fungsi ini.""" # body fungsi hasil = param1 + param2 return hasil # nilai yang dikembalikandef— kata kunci untuk mendefinisikan fungsi- Parameter — variabel input (hanya ada di dalam fungsi)
return— mengembalikan nilai; tanpareturn, fungsi mengembalikanNone- Docstring — opsional tapi sangat disarankan
Kenapa Fungsi Penting?
Dua prinsip dari MIT 6.100L:
- Decomposition — pecah masalah besar menjadi sub-masalah kecil
- Abstraction — sembunyikan detail implementasi, fokus pada apa bukan bagaimana
# Tanpa fungsi — repetitif dan susah diubahluas1 = 3.14159 * 5 ** 2luas2 = 3.14159 * 10 ** 2luas3 = 3.14159 * 7 ** 2
# Dengan fungsi — bersih, reusabledef luas_lingkaran(r): return 3.14159 * r ** 2
luas1 = luas_lingkaran(5)luas2 = luas_lingkaran(10)luas3 = luas_lingkaran(7)Scope dan Environment
Variabel di dalam fungsi tidak bisa diakses dari luar — ini namanya local scope.
def hitung(): x = 10 # variabel lokal return x
print(hitung()) # 10print(x) # NameError: name 'x' is not definedGlobal vs Local
nilai_global = 100 # variabel global
def tambah(n): nilai_lokal = 5 # hanya ada di sini return nilai_global + n + nilai_lokal # bisa baca global
print(tambah(10)) # 115Urutan Pencarian Nama (LEGB Rule)
Python mencari variabel dalam urutan: Local → Enclosing → Global → Built-in.
x = "global"
def luar(): x = "enclosing" def dalam(): # x = "local" # kalau ini ada, pakai local print(x) # pakai enclosing: "enclosing" dalam()
luar()Fungsi sebagai Objek
Di Python, fungsi adalah objek kelas satu — bisa disimpan di variabel, dimasukkan ke list, atau dijadikan argumen fungsi lain.
def kuadrat(x): return x ** 2
def kubik(x): return x ** 3
# Simpan fungsi di variabeloperasi = kuadratprint(operasi(5)) # 25
operasi = kubikprint(operasi(5)) # 125
# Masukkan fungsi ke listops = [kuadrat, kubik]for op in ops: print(op(3)) # 9, lalu 27Higher-Order Function
Fungsi yang menerima fungsi lain sebagai argumen:
def terapkan(fungsi, daftar): """Terapkan fungsi ke setiap elemen daftar.""" hasil = [] for item in daftar: hasil.append(fungsi(item)) return hasil
angka = [1, 2, 3, 4, 5]print(terapkan(kuadrat, angka)) # [1, 4, 9, 16, 25]print(terapkan(kubik, angka)) # [1, 8, 27, 64, 125]
# Python punya map() bawaan untuk iniprint(list(map(kuadrat, angka))) # [1, 4, 9, 16, 25]Lambda Function
Lambda adalah cara singkat membuat fungsi anonim (tanpa nama) — cocok untuk operasi sederhana satu baris.
# Fungsi biasadef tambah_dua(x): return x + 2
# Versi lambda (setara)tambah_dua = lambda x: x + 2
print(tambah_dua(5)) # 7
# Lambda dengan beberapa parameterkali = lambda x, y: x * yprint(kali(3, 4)) # 12Lambda paling berguna saat dipakai langsung sebagai argumen:
angka = [5, 2, 8, 1, 9, 3]
# Sort biasaprint(sorted(angka)) # [1, 2, 3, 5, 8, 9]
# Sort berdasarkan sisa bagi 3 (key function)print(sorted(angka, key=lambda x: x % 3)) # [3, 9, 1, 2, 5, 8]
# Sort list of tuple berdasarkan elemen keduadata = [("ana", 85), ("budi", 72), ("cici", 91)]print(sorted(data, key=lambda x: x[1]))# [('budi', 72), ('ana', 85), ('cici', 91)]Keyword dan Default Arguments
def perkenalan(nama, umur=17, kota="Jakarta"): """Default argument — nilai default dipakai kalau tidak diisi.""" print(f"Nama: {nama}, Umur: {umur}, Kota: {kota}")
perkenalan("Rifky") # pakai default umur & kotaperkenalan("Santi", 25) # override umurperkenalan("Budi", kota="Bandung") # keyword argument, skip umurperkenalan("Cici", umur=30, kota="Surabaya") # semua explicitAturan: argumen dengan default harus selalu di belakang argumen tanpa default.
Tuple
Tuple adalah koleksi data yang tidak bisa diubah (immutable) setelah dibuat. Ditulis dengan tanda kurung.
# Membuat tuplekoordinat = (3, 4)rgb = (255, 128, 0)satu_elemen = (42,) # perlu koma untuk tuple 1 elemen
# Akses elemen (sama dengan string)print(koordinat[0]) # 3print(koordinat[-1]) # 4
# Unpackingx, y = koordinatprint(f"x={x}, y={y}") # x=3, y=4
# Swap variabel dengan tuplea, b = 10, 20a, b = b, a # elegant swapprint(a, b) # 20 10Fungsi yang Mengembalikan Banyak Nilai
def min_maks(daftar): """Kembalikan nilai minimum dan maksimum sekaligus.""" return min(daftar), max(daftar)
angka = [5, 2, 8, 1, 9]minimum, maksimum = min_maks(angka)print(f"Min: {minimum}, Maks: {maksimum}") # Min: 1, Maks: 9List dan Mutabilitas
List mirip tuple tapi bisa diubah (mutable) — elemen bisa ditambah, dihapus, atau dimodifikasi.
buah = ["apel", "mangga", "jeruk"]
# Aksesprint(buah[0]) # "apel"print(buah[-1]) # "jeruk"print(buah[1:]) # ["mangga", "jeruk"]
# Modifikasibuah[0] = "pisang"print(buah) # ["pisang", "mangga", "jeruk"]
# Tambah elemenbuah.append("anggur") # tambah di akhirbuah.insert(1, "durian") # sisipkan di index 1
# Hapus elemenbuah.remove("mangga") # hapus nilai tertentudel buah[0] # hapus berdasarkan indexterakhir = buah.pop() # hapus & kembalikan elemen terakhir
# Operasi lainprint(len(buah)) # panjang listprint("jeruk" in buah) # True/Falsebuah.sort() # sort in-placebuah.reverse() # balik urutanList Comprehension
Cara ringkas membuat list baru dari list yang ada:
angka = [1, 2, 3, 4, 5]
# Cara lamakuadrat = []for x in angka: kuadrat.append(x ** 2)
# List comprehension (lebih ringkas)kuadrat = [x ** 2 for x in angka]print(kuadrat) # [1, 4, 9, 16, 25]
# Dengan kondisi (filter)genap_kuadrat = [x ** 2 for x in angka if x % 2 == 0]print(genap_kuadrat) # [4, 16]
# Nestedmatriks = [[i * j for j in range(1, 4)] for i in range(1, 4)]# [[1, 2, 3], [2, 4, 6], [3, 6, 9]]Aliasing dan Cloning
Ini salah satu konsep paling penting dan sering menyebabkan bug.
# Aliasing — dua nama menunjuk ke OBJEK YANG SAMAa = [1, 2, 3]b = a # b adalah alias a, bukan salinan!
b.append(4)print(a) # [1, 2, 3, 4] — a ikut berubah!print(b) # [1, 2, 3, 4]print(a is b) # True — benar-benar sama# Cloning — buat salinan independena = [1, 2, 3]b = a[:] # slice kosong = copy# atau: b = list(a)# atau: b = a.copy()
b.append(4)print(a) # [1, 2, 3] — tidak berubahprint(b) # [1, 2, 3, 4]print(a is b) # False — objek berbedaAturan praktis: kalau kamu ingin memodifikasi list tanpa mengubah aslinya, selalu clone dulu.
Hati-hati dengan Loop + Mutasi
# BUG — jangan mutasi list yang sedang di-loopL = [1, 2, 3, 4, 5]for item in L: if item % 2 == 0: L.remove(item) # hasil tidak terduga!print(L) # [1, 3, 5]? Tidak selalu...
# BENAR — loop copy, mutasi aslifor item in L[:]: # iterasi salinan if item % 2 == 0: L.remove(item) # amanDictionary
Dictionary menyimpan pasangan key–value. Key harus unik dan immutable (string, int, tuple).
# Membuat dictionarymahasiswa = { "nama": "Rifky", "nim": "19252259", "ipk": 3.85}
# Akses nilaiprint(mahasiswa["nama"]) # "Rifky"print(mahasiswa.get("ipk")) # 3.85print(mahasiswa.get("alamat", "tidak diketahui")) # default jika tidak ada
# Tambah / ubahmahasiswa["angkatan"] = 2019mahasiswa["ipk"] = 3.90
# Hapusdel mahasiswa["nim"]nilai = mahasiswa.pop("angkatan") # hapus & kembalikan nilai
# Iterasifor key in mahasiswa: print(key, ":", mahasiswa[key])
for key, value in mahasiswa.items(): print(f"{key}: {value}")
# Cek keberadaan keyprint("nama" in mahasiswa) # Trueprint("email" in mahasiswa) # FalseDictionary sebagai Counter
teks = "hello world"frekuensi = {}for huruf in teks: if huruf in frekuensi: frekuensi[huruf] += 1 else: frekuensi[huruf] = 1
print(frekuensi)# {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}
# Cara lebih ringkas dengan .get()frekuensi = {}for huruf in teks: frekuensi[huruf] = frekuensi.get(huruf, 0) + 1Ringkasan Perbandingan Struktur Data
| Tuple | List | Dictionary | |
|---|---|---|---|
| Syntax | (a, b) | [a, b] | {k: v} |
| Mutable? | ✗ | ✓ | ✓ |
| Ordered? | ✓ | ✓ | ✓ (Python 3.7+) |
| Akses | index | index | key |
| Duplikat? | ✓ | ✓ | Key unik |
| Use case | Koordinat, return multi-value | Koleksi data sejenis | Mapping key→value |
Artikel berikutnya: Testing, Debugging, Exception, dan Assertions — cara membuat program yang tahan banting dan mudah diperbaiki saat ada yang salah.
Sumber: MIT OpenCourseWare — 6.100L Introduction to CS and Programming Using Python, Fall 2022↗, Dr. Ana Bell. Lisensi CC BY-NC-SA 4.0.