Mengapa variabel yang dibuat di dalam sebuah function tidak bisa dibaca setelah function selesai? Mengapa print dan len bisa dipakai tanpa didefinisikan dan tanpa import? Dua pertanyaan tersebut bermuara pada satu mekanisme: scope. Setiap nama di Python hidup di dalam ruang lingkup tertentu, dan interpreter memiliki aturan baku tentang di mana mencari nama yang dibutuhkan. Memahami aturan ini menghilangkan separuh kebingungan variabel “hilang” atau “berubah sendiri” yang sering dialami pemula.
Namespace: Peta Nama ke Object #
Sebelum bicara scope, kita perlu konsep namespace: pemetaan dari nama ke object. Anggap namespace sebagai kamus — pada kenyataannya memang mirip dictionary — yang mencatat nama mana menunjuk ke object mana. Yang perlu diketahui: satu program Python tidak punya satu kamus tunggal, melainkan banyak kamus yang hidup berdampingan:
- Namespace global milik satu file module, berisi semua nama level atas.
- Namespace lokal dibuat segar setiap kali sebuah function dipanggil, berisi parameter dan variabel di dalamnya.
- Namespace builtins bawaan interpreter, berisi
print,len,range, dan lebih dari 150 nama siap pakai lainnya.
Fungsi total_gaji dan total_belanja berikut masing-masing punya variabel lokal bernama total — dan keduanya tidak saling bertabrakan:
def total_gaji():
total = 5000000
print("gaji :", total)
def total_belanja():
total = 25000
print("belanja:", total)
total_gaji()
total_belanja()Output yang Dihasilkan:
gaji : 5000000
belanja: 25000Kedua variabel total adalah dua object yang berbeda di dua namespace lokal yang berbeda. Setelah function selesai, namespace lokalnya dibuang — dan beserta itu seluruh variabel di dalamnya.
Aturan LEGB #
Saat interpreter Python menemukan sebuah nama (misalnya toko) di dalam badan function, interpreter mencarinya dengan urutan tetap yang dijuluki LEGB: Local, Enclosing, Global, Builtins:
| Urutan | Scope | Isi | Contoh nama |
|---|---|---|---|
| 1 | Local | parameter & variabel function yang sedang berjalan | harga, total di dalam function |
| 2 | Enclosing | namespace function di mana function ini didefinisikan (untuk function bersarang) | variabel function pembungkus |
| 3 | Global | namespace module tempat kode ditulis | variabel level atas file |
| 4 | Builtins | namespace bawaan interpreter | print, len, range |
Pencarian berhenti pada kecocokan pertama — seperti mencari kata di kamus dari yang paling spesifik. Jika sampai ujung daftar pun nama tidak ditemukan, interpreter memunculkan NameError.
Diagram di atas merangkum alur pencarian satu nama. Dua percobaan kecil berikut membuktikan dua jalurnya.
Membaca Global Dari Dalam Function #
Baca dan tulis berperilaku berbeda terhadap scope. Membaca nama global dari dalam function sah: pencarian L gagal, pencarian G berhasil:
nama_toko = "Toko Sinar Jaya"
def tampilkan_toko():
print("dalam fungsi:", nama_toko)
def ganti_nama():
nama_toko = "Toko Sinar Baru"
print("dalam fungsi:", nama_toko)
tampilkan_toko()
ganti_nama()
print("setelah fungsi:", nama_toko)Output yang Dihasilkan:
dalam fungsi: Toko Sinar Jaya
dalam fungsi: Toko Sinar Baru
setelah fungsi: Toko Sinar JayaMari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 1 (
nama_toko = "Toko Sinar Jaya"): assignment di level atas file membuat namanama_tokodi scope global. - Baris 3-4 (
print(...)dalamtampilkan_toko): namanama_tokotidak ada di scope lokal, pencarian lanjut ke global dan menemukannya — function membaca nilai"Toko Sinar Jaya". - Baris 7 (
nama_toko = "Toko Sinar Baru"dalamganti_nama): assignment di dalam badan function membuat nama baru di scope lokal, bukan mengubah nama global. Variabel lokalnama_tokomilikganti_namahanya hidup selama function itu berjalan. - Baris terakhir (
print("setelah fungsi:", nama_toko)): nilai global tetap"Toko Sinar Jaya"— tidak pernah tersentuh.
Variabel Lokal Tidak Terlihat dari Luar #
Arah sebaliknya tidak berlaku: nama lokal tidak pernah terlihat dari luar function. Setelah hitung_pajak selesai, variabel pajak di dalamnya sudah ikut dibuang bersama namespace lokalnya:
>>> def hitung_pajak(harga):
... pajak = harga // 10
... return pajak
...
>>> hitung_pajak(25000)
2500
>>> print(pajak)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'pajak' is not definedHasil 2500 berhasil dikembalikan lewat return dan bisa dipakai pemanggil — tetapi nama pajak itu sendiri tidak pernah keluar dari scope lokal. Jika pemanggil mencoba membaca pajak, pencarian lewat semua lapisan LEGB di scope pemanggil tidak menemukannya, dan NameError muncul.