LEGB kuralı — Python'daki ad alanı (scoping) arama kuralıdır. Kısaltma şu şekilde açılmaktadır:
len, list, vb.).Python bir değişkenle karşılaştığında, önce yerelde, sonra iç içe fonksiyonlarda, ardından modülün küresel alanında, ve son olarak yerleşik nesnelerin ad alanında arama yapar:
def outer(): x = 'enclosing' def inner(): x = 'local' print(x) inner() outer() # 'local'
Eğer inner() içindeki x atamasını kaldırırsanız, Python x'i enclosing scope (outer) içinden alır. Eğer orada da değişken yoksa — küresel olarak arar, sonra yerleşiklerden.
Dış seviyedeki bir değişkeni değiştirmek için
nonlocalveyaglobaltanımlamayı unutursanız, fonksiyonun davranışı nasıl değişir?
Cevap:
Eğer iç içe fonksiyon içinde dış scope'daki bir değişkeni nonlocal (veya modülde değişken varsa global) tanımlamadan değiştirmeye çalışırsanız, Python yeni bir yerel değişken oluşturur ve dış değişkeni değiştirmez.
Örnek:
x = 10 def foo(): x = 20 # Bu yeni bir yerel x, küresel değişken değişmez foo() print(x) # 10
Küresel x'i değiştirmek için:
def foo(): global x x = 20
Dış fonksiyonlardaki değişkenler için — nonlocal kullanın.
Hikaye 1
Eğitim projesinde çağrı sayısını saymak için iç içe fonksiyonlar kullandılar. Geliştirici şunu yazdı:
def counter(): count = 0 def inc(): count += 1 return count return inc
Ama UnboundLocalError ortaya çıktı, çünkü inc() içinde count yeni bir değişken olarak değerlendirildi (yerel count oluşturuldu). Çözüm: count'u nonlocal olarak tanımlamak.
Hikaye 2
Bir web uygulamasında, işleyicide belirlenen küreli cache'i değiştirmek istediler:
cache = {} def add_to_cache(key, value): cache[key] = value
Ancak işlev içinde cache'i tamamen yeniden yazmaya çalışsaydık, örneğin cache = {key: value}, bu yeni bir yerel cache oluştururdu, bu da küresel olanla bağlantılı değildi, çünkü global cache tanımı eksikti.
Hikaye 3
Büyük bir ETL sisteminde bir hata ile karşılaşıldı: programcılar, result değişkenini fonksiyon içinde açık bir şekilde başlatmadan bıraktılar, dış scope'dan alınacağını bekliyorlardı. Ama birkaç iterasyondan sonra sonuç bozulmaya başladı, çünkü içeride result += value yazıyordu, result = result + value (nonlocal/global olmadan) değil — bu nedenle result her çağrıda yeniden başlatılıyordu.