Python, çeşitli kapsamlar için her şeyi sözlükte tutması bakımından biraz garip. Orijinal a, b, c en üst kapsamdadır ve bu yüzden en üstteki sözlüktedir. Fonksiyonun kendi sözlüğü vardır. print(a)
Ve print(b)
ifadelerine ulaştığınızda, sözlükte bu ada göre hiçbir şey yoktur, bu nedenle Python listeye bakar ve bunları global sözlükte bulur.
Şimdi c+=1
, elbette, buna eşdeğeriz c=c+1
. Python bu satırı taradığında, "aha, c adında bir değişken var, bunu yerel kapsam sözlüğüme koyacağım" diyor. Ardından, ödevin sağ tarafında c için c değeri aramaya başladığında , henüz değeri olmayan c adlı yerel değişkenini bulur ve hatayı atar.
global c
Yukarıda belirtilen ifade , ayrıştırıcıya c
global kapsamdan kullandığını ve yeni bir taneye ihtiyaç duymadığını bildirir .
Satırda bir sorun olduğunu söylemesinin nedeni, kod üretmeye çalışmadan önce isimleri etkili bir şekilde aramasıdır ve bu yüzden bir anlamda gerçekten bu satırı yaptığını düşünmemektedir. Bunun bir kullanılabilirlik hatası olduğunu iddia ediyorum, ancak bir derleyicinin mesajlarını çok ciddiye almamayı öğrenmek genellikle iyi bir uygulamadır .
Herhangi bir rahatlık varsa, Guido'nun Her Şeyi Açıklayan sözlükler hakkında yazdığı bir şey bulmadan önce muhtemelen aynı günü kazıp bir gün geçirdim.
Güncelleme, yorumlara bakın:
Kodu iki kez taramaz, ancak kodu iki aşamada tarar: lexing ve ayrıştırma.
Bu kod satırının ayrıştırmasının nasıl çalıştığını düşünün. Lexer kaynak metni okur ve dilbilgisinin "en küçük bileşenleri" olan lexemes'e böler. Yani çizgiye çarptığında
c+=1
onu böyle bir şeye ayırır
SYMBOL(c) OPERATOR(+=) DIGIT(1)
Ayrıştırıcı sonunda bunu bir ayrıştırma ağacına dönüştürmek ve yürütmek ister, ancak bir ödev olduğundan, daha önce yerel sözlükte c adını arar, görmez ve sözlüğe ekler, işaretler başlatılmamış olarak. Tamamen derlenmiş bir dilde, sadece sembol tablosuna gidip ayrışmayı bekleyecekti, ancak ikinci bir geçiş lüksüne sahip olamayacağı için, lexer daha sonra hayatı kolaylaştırmak için biraz ekstra iş yapıyor. Ancak, o zaman OPERATÖR'ü görür, kuralların "bir operatörünüz + = sol tarafın başlatılmış olması gerekir" der ve "whoops!"
Buradaki nokta , çizginin ayrıştırılmasına henüz başlamamış olmasıdır . Tüm bunlar gerçek ayrışmaya hazırlanıyor, bu nedenle satır sayacı bir sonraki satıra ilerlemedi. Böylece hatayı işaret ettiğinde, hala bir önceki satırda olduğunu düşünür.
Dediğim gibi, bunun bir kullanılabilirlik hatası olduğunu iddia edebilirsiniz, ama aslında oldukça yaygın bir şey. Bazı derleyiciler bu konuda daha dürüst davranırlar ve "XXX satırında veya çevresinde hata" derler.