Bir if ifadesinde başlatılan değişkenin kapsamı nedir?


266

Python'da yeniyim, bu muhtemelen basit bir kapsam sorusu. Bir Python dosyasındaki (modül) aşağıdaki kod beni biraz karıştırıyor:

if __name__ == '__main__':
    x = 1

print x

Çalıştığım diğer dillerde, xdeğişken ifade için yerel olduğundan ifve bunun dışında olmamalıdır , bu kod bir istisna atar . Ancak bu kod yürütülür ve 1 yazdırılır. Herkes bu davranışı açıklayabilir mi? Bir modülde oluşturulan tüm değişkenler tüm modül için global / kullanılabilir mi?


17
Başka bir cilvesi farkında olmayabilir: eğer ifdeyimi yukarıda tutmaz (yani gerçek __name__olduğunu değil '__main__' bunu üst düzey yürütme yerine modülü aldığınızda, örneğin), sonra xbağlanmış ve daha sonraki edilmiş asla print xbeyanı atar NameError: name 'x' is not defined.
Noel Baba

Yanıtlar:


302

Python değişkenleri atandıkları en içteki işleve, sınıfa veya modüle dahil edilir. Kontrol blokları ifve whilebloklar sayılmaz, bu nedenle birif hala bir fonksiyona, sınıfa veya modüle dahil edilir.

(Örtülü işlevler bir jeneratör ifadesi veya liste / set / dict anlama tarafından tanımlanan yapmak Onlardan herhangi birine bir atama deyimi şeyler olamaz. Olarak lambda ifadeleri yapın sayımı, ancak lambda parametreleri ve forfıkra hedefleri örtülü atama vardır.)



105

Evet, aynı "yerel kapsamda "lar ve aslında böyle bir kod Python'da yaygındır:

if condition:
  x = 'something'
else:
  x = 'something else'

use(x)

xÖrneğin C veya Java'da olduğu gibi koşuldan önce bildirilmedi veya başlatılmadığını unutmayın .

Başka bir deyişle, Python'un blok düzeyinde kapsamları yoktur. Bununla birlikte, aşağıdaki gibi örneklere dikkat edin.

if False:
    x = 3
print(x)

bu da açıkça bir NameErroristisna oluşturur.


42

Python kapsamı şu sırayı izler:

  • Yerel kapsamı arayın

  • Çevreleyen işlevlerin kapsamını arayın

  • Global kapsamda arama yapın

  • Yerleşiklerde ara

( kaynak )

Bildirim o ifve diğer döngü / dallanma yapılar yer almamakta - Bir bildirilen şey yani sadece sınıflar, fonksiyonlar ve modüller, Python kapsamını sağlamak ifşey dışında blok decleared olarak bloğun aynı kapsama sahiptir. Değişkenler derleme zamanında kontrol edilmez, bu nedenle diğer diller bir istisna atar. Python'da, değişken istediğiniz anda mevcut olduğu sürece, herhangi bir istisna atılmaz.


9

Eli'nin dediği gibi, Python değişken bildirim gerektirmez. C'de şunu söylerdiniz:

int x;
if(something)
    x = 1;
else
    x = 2;

ancak Python bildirimi örtüktür, bu nedenle x'e atadığınızda otomatik olarak bildirilir. Çünkü Python dinamik olarak yazılmıştır - statik olarak yazılmış bir dilde çalışmaz, çünkü kullanılan yola bağlı olarak, bir değişken bildirilmeden kullanılabilir. Bu, statik olarak yazılmış bir dilde derleme zamanında yakalanır, ancak dinamik olarak yazılmış bir dille izin verilir.

Statik olarak yazılan bir dilin, ifbu sorun nedeniyle değişkenlerin deyimler dışında bildirilmesi ile sınırlı olmasının tek nedeni . Dinamiği kucaklayın!


9

C gibi dillerden farklı olarak, bir Python değişkeni, yalnızca en içteki "blokta" değil, göründüğü fonksiyonun (veya sınıfın veya modülün) tamamı için geçerlidir. Sanki int xPython'da değişkenleri bildirmeniz gerekmemesi dışında, işlevin (ya da sınıfın ya da modülün) en üstünde beyan etmişsinizdir.

Değişkenin varlığının xyalnızca çalışma zamanında - yani print xifadeye geldiğinizde - kontrol edildiğini unutmayın . Eğer __name__eşit vermedi "__main__"o zaman istisna alacağı: NameError: name 'x' is not defined.


Sınıflar bir kapsam oluşturmaz; sınıftaki bir "yerel" değişken, sınıfın oluşturma üzerine diktiğine basitçe eklenir.
chepner

3

Evet. Aynı zamanda forkapsam için de geçerlidir . Ama elbette işlevleri değil.

Örneğinizde: ifadedeki koşul ifyanlışsa, xyine de tanımlanmaz.


2

bu kodu komut satırından yürütüyorsunuz, bu nedenle ifkoşullar doğrudur ve xayarlanmıştır. Karşılaştırmak:

>>> if False:
    y = 42


>>> y
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    y
NameError: name 'y' is not defined

0

Ayrıca, Python türleri yalnızca çalışma zamanında kontrol edildiğinden, aşağıdaki gibi kodlara sahip olabileceğinizi unutmayın:

if True:
    x = 2
    y = 4
else:
    x = "One"
    y = "Two"
print(x + y)

Ancak kod türü sorunları nedeniyle hatasız çalışacağı diğer yolları düşünmekte sorun yaşıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.