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:

python
def total_gaji():
    total = 5000000
    print("gaji   :", total)

def total_belanja():
    total = 25000
    print("belanja:", total)

total_gaji()
total_belanja()

Output yang Dihasilkan:

text
gaji   : 5000000
belanja: 25000

Kedua 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:

UrutanScopeIsiContoh nama
1Localparameter & variabel function yang sedang berjalanharga, total di dalam function
2Enclosingnamespace function di mana function ini didefinisikan (untuk function bersarang)variabel function pembungkus
3Globalnamespace module tempat kode ditulisvariabel level atas file
4Builtinsnamespace bawaan interpreterprint, 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:

python
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:

text
dalam fungsi: Toko Sinar Jaya
dalam fungsi: Toko Sinar Baru
setelah fungsi: Toko Sinar Jaya

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 1 (nama_toko = "Toko Sinar Jaya"): assignment di level atas file membuat nama nama_toko di scope global.
  2. Baris 3-4 (print(...) dalam tampilkan_toko): nama nama_toko tidak ada di scope lokal, pencarian lanjut ke global dan menemukannya — function membaca nilai "Toko Sinar Jaya".
  3. Baris 7 (nama_toko = "Toko Sinar Baru" dalam ganti_nama): assignment di dalam badan function membuat nama baru di scope lokal, bukan mengubah nama global. Variabel lokal nama_toko milik ganti_nama hanya hidup selama function itu berjalan.
  4. 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:

python
>>> 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 defined

Hasil 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.