ProgramlamaPython geliştirici

Python'daki 'LEGB kuralı' nedir? Değişken adı aramasında nasıl çalışır? Bu kuralın yanlış anlaşılmasının sıradışı hatalara yol açtığı durumlara örnekler verin.

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

LEGB kuralı — Python'daki ad alanı (scoping) arama kuralıdır. Kısaltma şu şekilde açılmaktadır:

  • Local — yerel ad alanı (fonksiyon içinde);
  • Enclosing — tüm iç içe geçmiş fonksiyonların ad alanları;
  • Global — modül alanı (küresel değişkenler);
  • Builtin — Python'un yerleşik isimleri (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.


Kapalı bir soru.

Dış seviyedeki bir değişkeni değiştirmek için nonlocal veya global tanı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.


Konunun ince detaylarından ötürü gerçekleşen hatalara örnekler.


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.