Penjelasan Cakupan Variabel Python dan Aturan LEGB
Pelajari seluk-beluk cakupan variabel dan kenali aturan 'LEGB'. Anda juga akan melihat skenario penggunaan keyword global dan nonlocal secara langsung.
Melihat pesan “name is not defined” atau “local variable referenced before assignment” setelah menulis beberapa baris kode itu menjengkelkan. Kodenya terlihat baik, namun Python tidak sependapat. Penyebab utamanya hampir selalu soal cakupan (scope): di mana sebuah nama terlihat dan ke objek mana ia merujuk pada saat itu.
Begitu Anda memahami cara pencarian nama di Python—sering diringkas sebagai aturan LEGB—kesalahan ini menjadi dapat diprediksi dan mudah diperbaiki. Dalam tutorial ini, saya akan membahas variabel dan cakupan di Python selangkah demi selangkah.
Apa Itu Variabel?
Variabel adalah nama yang diikat ke sebuah objek. Di Python, Anda membuat ikatan dengan operator penugasan =. Nama tidak bertipe; nama dapat menunjuk ke objek apa pun (string, int, list, function, dan sebagainya).
customer_name ="Ava Torres"
order_count =1
total_cents =1+2*300# evaluated first, then boundDidukung oleh
Ikuti aturan dan konvensi ini saat memberi nama variabel untuk menghindari error sintaks dan bug tersembunyi.
Gunakan huruf, angka, dan garis bawah saja; nama tidak boleh diawali angka.
Jangan gunakan keyword seperti True, for, atau class sebagai nama.
Hindari membayangi (shadowing) built-in seperti list, dict, sum, atau max.
Gunakan snake_case demi keterbacaan (PEP 8).
Contoh berikut memperlihatkan apa yang tidak boleh dilakukan dan error yang akan muncul di Python:
first string value ="First string"# spaces not allowed# SyntaxError: invalid syntax
1st_value =10# cannot start with a digit# SyntaxError: invalid decimal literalTrue="yes"# cannot assign to a keyword# SyntaxError: cannot assign to TrueDidukung oleh
Cara Kerja Scope Python (LEGB)
Scope adalah wilayah kode tempat sebuah nama terlihat. Saat Anda menggunakan sebuah nama, Python mencarinya dalam urutan berikut (LEGB):
Local: scope fungsi saat ini.
Enclosing: scope fungsi luar (untuk fungsi bertingkat).
Global: tingkat atas modul (namespace modul).
Built-in: nama yang didefinisikan oleh Python di builtins (misalnya, len, print).
Nama hidup di dalam namespace (anggaplah sebagai kamus yang memetakan nama ke objek). Scope menentukan namespace mana yang dirujuk Python untuk menyelesaikan sebuah nama pada titik tertentu di kode.
Scope lokal
Nama yang ditugaskan di dalam fungsi bersifat lokal untuk fungsi itu kecuali dinyatakan lain. Nama tersebut tidak terlihat di luar fungsi.
defshow_order_id():
order_id =42print("inside function:", order_id)
show_order_id()print("outside function:", order_id)# NameErrorDidukung oleh
Python memutuskan scope saat kompilasi. Jika sebuah fungsi melakukan penugasan ke sebuah nama di mana pun di tubuhnya, semua penggunaan nama tersebut di fungsi dianggap lokal—menyebabkan UnboundLocalError umum ketika Anda membaca sebelum menugaskan:
discount_rate =0.10# module-level (global)defprice_with_discount(amount_cents):print("configured discount:", discount_rate)# looks local because of the assignment below
discount_rate =0.20# assignment makes 'discount_rate' local in this functionreturnint(amount_cents *(1- discount_rate))# UnboundLocalError: cannot access local variable 'discount_rate' where it is not associated with a valueDidukung oleh
Untuk menggunakan nama tingkat modul di dalam fungsi, hindari menugaskannya atau tandai sebagai global (dibahas di bawah).
Scope enclosing (closure)
Fungsi bertingkat dapat melihat nama dari fungsi yang langsung melingkupinya. Untuk mengikat ulang nama tersebut (bukan sekadar membacanya), nyatakan sebagai nonlocal.
defmake_step_counter():
count =0# enclosing scope for 'increment'defincrement():nonlocal count # rebind the 'count' in the nearest enclosing function
count +=1return count
return increment
step = make_step_counter()print(step())# 1print(step())# 2Didukung oleh
Tanpa nonlocal, penugasan ke count di dalam increment() akan membuat nama lokal baru dan membiarkan count luar tidak berubah.
Scope global
Nama yang ditugaskan di tingkat atas modul berada di namespace global modul. Fungsi mana pun dapat membacanya. Untuk menugaskan ke nama tingkat modul dari dalam fungsi, nyatakan sebagai global.
greeting ="Hello"defgreet_city(city_name):print(greeting, city_name)# reads globaldefset_greeting(new_greeting):global greeting
greeting = new_greeting # rebinds global
greet_city("Nairobi")# Hello Nairobi
set_greeting("Hi")
greet_city("Nairobi")# Hi NairobiDidukung oleh
Gunakan global secara hemat. Lebih baik meneruskan nilai sebagai parameter dan mengembalikan hasil agar kode tetap mudah diuji dan diprediksi.
Scope built-in (dan catatan tentang keyword)
Scope built-in berisi nama seperti len, print, dan Exception. Hindari membayangi nama-nama ini, jika tidak Anda akan kehilangan akses ke built-in tersebut pada scope itu.
list=[1,2,3]# shadows the built-in 'list' constructorlist("abc")# TypeError: 'list' object is not callabledellist# fix by deleting the shadowing nameDidukung oleh
Keyword (seperti if, for, def) adalah bagian dari sintaks Python, bukan namespace built-in, dan tidak pernah dapat digunakan sebagai identifier.
Blok, Loop, dan Comprehension
Pernyataan blok dan comprehension di Python memiliki perilaku scoping khusus yang sering mengejutkan pengembang dari bahasa lain.
Tidak ada scope blok untuk if/for/while/with
Penugasan di dalam blok-blok ini memengaruhi scope yang menaunginya (fungsi atau modul). Variabel loop juga tetap terdefinisi setelah loop berakhir.
ifTrue:
status ="ready"print(status)# "ready"for i inrange(3):passprint(i)# 2 (the last value from the loop)Didukung oleh
Comprehension mengisolasi variabel iterasinya
List, dict, dan set comprehension memiliki scope lokal sendiri untuk variabel loop. Variabel iterasi tidak bocor ke scope di sekitarnya.
numbers =[1,2,3][x for x in numbers]print("x"inglobals()or"x"inlocals())# FalseDidukung oleh
Python 3.12 (PEP 709) melakukan inline comprehension demi kecepatan sambil mempertahankan isolasi ini; Anda tetap mendapatkan variabel loop yang jelas dan tidak bocor dengan eksekusi yang lebih cepat.
Menggunakan Keyword global
Nyatakan sebuah nama sebagai global di dalam fungsi saat Anda perlu mengikat ulang variabel tingkat modul. Letakkan deklarasi di dekat awal fungsi agar jelas variabel mana yang Anda ubah.
tax_rate =0.08defconfigure_tax(rate):global tax_rate
tax_rate =float(rate)deftotal_with_tax(cents):returnint(cents *(1+ tax_rate))
configure_tax(0.10)print(total_with_tax(1000))# 1100Didukung oleh
Menggunakan Keyword nonlocal
Gunakan nonlocal untuk mengikat ulang sebuah nama dari scope fungsi terdekat yang melingkupinya. Ini umum pada closure yang mempertahankan state.
defmake_accumulator(start=0):
total = start
defadd(amount):nonlocal total
total += amount
return total
return add
acc = make_accumulator()print(acc(5))# 5print(acc(10))# 15Didukung oleh
Menggunakan nonlocal untuk nama yang tidak didefinisikan di fungsi yang melingkupi adalah SyntaxError. Jika namanya global, gunakan global.
locals() dan globals() pada 2025
Fungsi-fungsi ini berguna untuk inspeksi dan debugging, bukan untuk memperbarui variabel. Mulai Python 3.13 (PEP 667), setiap pemanggilan locals() di dalam fungsi mengembalikan snapshot independen. Mengedit snapshot tersebut tidak mengubah variabel lokal sesungguhnya. Saya mengonfirmasi perilaku ini dengan menjalankan cuplikan berikut pada Python 3.13:
defprobe():
project ="alpha"
snap1 =locals()
snap1["project"]="beta"# edits the snapshot only
observed = project # still "alpha"
snap2 =locals()# new snapshotreturn snap1["project"], observed, snap2["project"]print(probe())# ('beta', 'alpha', 'alpha')Didukung oleh
Gunakan globals() dengan cara serupa untuk namespace modul. Saat menulis kode aplikasi, lebih utamakan parameter dan nilai kembalian eksplisit daripada pencarian dinamis.
Kesalahan Umum dan Cara Memperbaikinya
Kesalahan-kesalahan ini menyumbang sebagian besar error terkait scope yang saya lihat di praktik.
UnboundLocalError akibat penugasan di dalam fungsi: Python menganggap sebuah nama sebagai lokal jika ditugaskan di mana pun dalam fungsi. Pindahkan pembacaan setelah penugasan, ganti nama, atau tambahkan global/nonlocal sesuai kebutuhan.
Berharap ada scope blok: Nama yang ditugaskan di if/for/while/with tetap ada di scope yang menaunginya. Gunakan fungsi pembantu yang lebih sempit untuk membatasi scope.
Membayangi built-in: Hindari nama seperti list, dict, sum, id, atau min. Pilih nama deskriptif seperti customer_list atau min_allowed.
Lupa nonlocal di closure: Jika Anda bermaksud memperbarui variabel fungsi luar, nyatakan sebagai nonlocal. Jika tidak, Anda membuat lokal baru dan nilai luar tidak berubah.
Membingungkan keyword dengan built-in: Keyword (sintaks) tidak pernah bisa digunakan sebagai nama. Built-in bisa dibayangi tetapi sebaiknya dihindari.
Praktik Terbaik agar Scope Tetap Sederhana
Kebiasaan-kebiasaan ini membuat kode lebih mudah dibaca, diuji, dan di-debug.
Utamakan fungsi kecil dan terfokus. Definisikan variabel pada scope tersempit yang memungkinkan.
Lewatkan data masuk dan keluar melalui parameter dan nilai kembalian. Minimalkan state tingkat modul.
Gunakan closure secara sengaja. Dokumentasikan nama luar mana yang ditangkap fungsi bertingkat, dan gunakan nonlocal hanya saat benar-benar perlu mengikat ulang.
Pilih nama yang deskriptif dan tidak berbenturan. Garis bawah di depan (misalnya, _cache) menandakan penggunaan internal.
Perlakukan locals()/globals() sebagai diagnostik read-only, bukan mekanisme konfigurasi.
Kesimpulan
Python menyelesaikan nama dengan mencari dari Local → Enclosing → Global → Built-in. Memahami urutan itu—dan kapan menggunakan global atau nonlocal—menghilangkan kesalahan umum seperti NameError dan UnboundLocalError. Simpan variabel pada scope sekecil mungkin, hindari membayangi built-in, dan gunakan closure secara terukur. Dengan model mental itu, fungsi Anda berperilaku dapat diprediksi, dan scope tidak lagi menjadi sumber kejutan.
Saya telah bekerja di berbagai industri dan mengenakan banyak peran: pengembang perangkat lunak, peneliti machine learning, ilmuwan data, manajer produk. Namun pada intinya, saya adalah seorang programmer yang gemar belajar dan berbagi pengetahuan!
Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Selami ilmu data dengan Python dan pelajari cara menganalisis serta memvisualisasikan data Anda secara efektif. Tak perlu pengalaman atau keterampilan coding.
Melihat pesan “name is not defined” atau “local variable referenced before assignment” setelah menulis beberapa baris kode itu menjengkelkan. Kodenya terlihat baik, namun Python tidak sependapat. Penyebab utamanya hampir selalu soal cakupan (scope): di mana sebuah nama terlihat dan ke objek mana ia merujuk pada saat itu.
Begitu Anda memahami cara pencarian nama di Python—sering diringkas sebagai aturan LEGB—kesalahan ini menjadi dapat diprediksi dan mudah diperbaiki. Dalam tutorial ini, saya akan membahas variabel dan cakupan di Python selangkah demi selangkah.
Apa Itu Variabel?
Variabel adalah nama yang diikat ke sebuah objek. Di Python, Anda membuat ikatan dengan operator penugasan
=. Nama tidak bertipe; nama dapat menunjuk ke objek apa pun (string, int, list, function, dan sebagainya).Ikuti aturan dan konvensi ini saat memberi nama variabel untuk menghindari error sintaks dan bug tersembunyi.
True,for, atauclasssebagai nama.list,dict,sum, ataumax.snake_casedemi keterbacaan (PEP 8).Contoh berikut memperlihatkan apa yang tidak boleh dilakukan dan error yang akan muncul di Python:
Cara Kerja Scope Python (
LEGB)Scope adalah wilayah kode tempat sebuah nama terlihat. Saat Anda menggunakan sebuah nama, Python mencarinya dalam urutan berikut (LEGB):
builtins(misalnya,len,print).Nama hidup di dalam namespace (anggaplah sebagai kamus yang memetakan nama ke objek). Scope menentukan namespace mana yang dirujuk Python untuk menyelesaikan sebuah nama pada titik tertentu di kode.
Scope lokal
Nama yang ditugaskan di dalam fungsi bersifat lokal untuk fungsi itu kecuali dinyatakan lain. Nama tersebut tidak terlihat di luar fungsi.
Python memutuskan scope saat kompilasi. Jika sebuah fungsi melakukan penugasan ke sebuah nama di mana pun di tubuhnya, semua penggunaan nama tersebut di fungsi dianggap lokal—menyebabkan
UnboundLocalErrorumum ketika Anda membaca sebelum menugaskan:Untuk menggunakan nama tingkat modul di dalam fungsi, hindari menugaskannya atau tandai sebagai
global(dibahas di bawah).Scope enclosing (closure)
Fungsi bertingkat dapat melihat nama dari fungsi yang langsung melingkupinya. Untuk mengikat ulang nama tersebut (bukan sekadar membacanya), nyatakan sebagai
nonlocal.Tanpa
nonlocal, penugasan kecountdi dalamincrement()akan membuat nama lokal baru dan membiarkancountluar tidak berubah.Scope global
Nama yang ditugaskan di tingkat atas modul berada di namespace global modul. Fungsi mana pun dapat membacanya. Untuk menugaskan ke nama tingkat modul dari dalam fungsi, nyatakan sebagai
global.Gunakan
globalsecara hemat. Lebih baik meneruskan nilai sebagai parameter dan mengembalikan hasil agar kode tetap mudah diuji dan diprediksi.Scope built-in (dan catatan tentang keyword)
Scope built-in berisi nama seperti
len,print, danException. Hindari membayangi nama-nama ini, jika tidak Anda akan kehilangan akses ke built-in tersebut pada scope itu.Keyword (seperti
if,for,def) adalah bagian dari sintaks Python, bukan namespace built-in, dan tidak pernah dapat digunakan sebagai identifier.Blok, Loop, dan Comprehension
Pernyataan blok dan comprehension di Python memiliki perilaku scoping khusus yang sering mengejutkan pengembang dari bahasa lain.
Tidak ada scope blok untuk
if/for/while/withPenugasan di dalam blok-blok ini memengaruhi scope yang menaunginya (fungsi atau modul). Variabel loop juga tetap terdefinisi setelah loop berakhir.
Comprehension mengisolasi variabel iterasinya
List, dict, dan set comprehension memiliki scope lokal sendiri untuk variabel loop. Variabel iterasi tidak bocor ke scope di sekitarnya.
Python 3.12 (PEP 709) melakukan inline comprehension demi kecepatan sambil mempertahankan isolasi ini; Anda tetap mendapatkan variabel loop yang jelas dan tidak bocor dengan eksekusi yang lebih cepat.
Menggunakan Keyword
globalNyatakan sebuah nama sebagai
globaldi dalam fungsi saat Anda perlu mengikat ulang variabel tingkat modul. Letakkan deklarasi di dekat awal fungsi agar jelas variabel mana yang Anda ubah.Menggunakan Keyword
nonlocalGunakan
nonlocaluntuk mengikat ulang sebuah nama dari scope fungsi terdekat yang melingkupinya. Ini umum pada closure yang mempertahankan state.Menggunakan
nonlocaluntuk nama yang tidak didefinisikan di fungsi yang melingkupi adalahSyntaxError. Jika namanya global, gunakanglobal.locals()danglobals()pada 2025Fungsi-fungsi ini berguna untuk inspeksi dan debugging, bukan untuk memperbarui variabel. Mulai Python 3.13 (PEP 667), setiap pemanggilan locals() di dalam fungsi mengembalikan snapshot independen. Mengedit snapshot tersebut tidak mengubah variabel lokal sesungguhnya. Saya mengonfirmasi perilaku ini dengan menjalankan cuplikan berikut pada Python 3.13:
Gunakan
globals()dengan cara serupa untuk namespace modul. Saat menulis kode aplikasi, lebih utamakan parameter dan nilai kembalian eksplisit daripada pencarian dinamis.Kesalahan Umum dan Cara Memperbaikinya
Kesalahan-kesalahan ini menyumbang sebagian besar error terkait scope yang saya lihat di praktik.
UnboundLocalErrorakibat penugasan di dalam fungsi: Python menganggap sebuah nama sebagai lokal jika ditugaskan di mana pun dalam fungsi. Pindahkan pembacaan setelah penugasan, ganti nama, atau tambahkan global/nonlocal sesuai kebutuhan.customer_listataumin_allowed.nonlocaldi closure: Jika Anda bermaksud memperbarui variabel fungsi luar, nyatakan sebagai nonlocal. Jika tidak, Anda membuat lokal baru dan nilai luar tidak berubah.Praktik Terbaik agar Scope Tetap Sederhana
Kebiasaan-kebiasaan ini membuat kode lebih mudah dibaca, diuji, dan di-debug.
_cache) menandakan penggunaan internal.Kesimpulan
Python menyelesaikan nama dengan mencari dari Local → Enclosing → Global → Built-in. Memahami urutan itu—dan kapan menggunakan global atau nonlocal—menghilangkan kesalahan umum seperti
NameErrordanUnboundLocalError. Simpan variabel pada scope sekecil mungkin, hindari membayangi built-in, dan gunakan closure secara terukur. Dengan model mental itu, fungsi Anda berperilaku dapat diprediksi, dan scope tidak lagi menjadi sumber kejutan.