Döngüler için Python'da kapsam belirleme


177

Python'un kapsam belirleme kurallarını sormuyorum; Genelde döngülerin Python'da kapsamlandırmanın nasıl çalıştığını anlıyorum . Benim sorum, tasarım kararlarının neden bu şekilde verildiğidir. Örneğin (amaçlanan kelime yok):

for foo in xrange(10):
    bar = 2
print(foo, bar)

Yukarıdakiler yazdırılacaktır (9,2).

Bu bana garip geldi: 'foo' gerçekten sadece döngüyü kontrol ediyor ve döngü içinde 'bar' tanımlandı. Neden 'bar' döngü dışında erişilebilir olması gerektiğini anlayabilirim (aksi takdirde, döngüler çok sınırlı işlevsellik olurdu). Anlamadığım şey, kontrol değişkeninin döngü çıktıktan sonra neden kapsamda kalmasının gerekli olduğudur. Deneyimlerime göre, küresel ad alanını tıkar ve diğer dillerdeki tercümanlar tarafından yakalanacak hataları izlemeyi zorlaştırır.


6
forDöngünün global ad alanınızı karıştırmasını istemiyorsanız, bir işleve sarın. Kapanışlar bolca!
jathanizm

24
Genel ad alanında (nadir) bir döngü çalıştırmadığınız sürece, yerel bir ad alanını karıştırır.
Glenn Maynard

3
Bu olmasaydı, daha sonra döngü içinde bıraktığınız noktada işlemeye nasıl devam edersiniz? Kontrol değişkenini döngüden önce tanımlamanız yeterli mi?
endolith

9
@endolith Evet ... Neden buna gerek yok?
Steven Lu

3
insanlar alışık olduklarını tercih edecekler. Bu tür şeylerin bu tür şeylere alışmış ve farklı bir dile geçerken acı verici bir süreçten geçmek zorunda olan python kodlayıcıya zarar verdiğini söyleyebilirim. Geri kalanımız için, sanırım düzgün küçük bir kısayol.
Steven Lu

Yanıtlar:


107

En olası cevap, sadece dilbilgisini basit tutması, benimsenmesi için tökezleyen bir blok olmamış olması ve birçoğunun, bir döngü yapısı içinde ona bir adın ait olduğu kapsamı netleştirmek zorunda kalmamaktan memnun olmasıdır. Değişkenler bir kapsam dahilinde bildirilmez, atama ifadelerinin yeri tarafından ima edilir. globalAnahtar kelime sadece bu nedenle (bu atamayı belirtmek için küresel bir kapsam yapılır) için mevcuttur.

Güncelleme

İşte konuyla ilgili güzel bir tartışma: http://mail.python.org/pipermail/python-ideas/2008-October/002109.html

Döngü değişkenlerini döngüye yerel yapmak için önceki öneriler, döngüden çıktıktan sonra değerini koruyan döngü değişkenine dayanan mevcut kod sorununa rastladı ve bunun istenen bir özellik olarak göründüğü görülüyor.

Kısacası, muhtemelen Python topluluğunda suçlayabilirsiniz: P


2
İndüksiyon değişkeninin kapsamı döngünün gövdesi ile sınırlı olsaydı gramer nasıl daha karmaşık olurdu? Böyle bir değişiklik, grameriyle değil, Python'daki anlamsal analizle sınırlı olacaktır.
Charles

6
Python'da döngüler blok değildir. Bu tür davranışsal değişiklikler ya dilbilgisini temelden değiştirmeyi ya da özel bir durum sunmayı gerektirir. Bir indüksiyon değişkeni kavramı mevcut dilbilgisinde de ifade edilmez. Dilbilgisi, tercümanın nasıl yorumlayacağına dair sözleşme sağlar. Demek istediğim, bu davranıştaki bir değişikliğin dilbilgisini daha karmaşık hale getirmeden nasıl yapılabileceğini öngöremiyorum. Tasarım kararının yan etkisi bir özellik haline geldiğinden hepsi tartışmalı.
Jeremy Brown

1
Bu yazı burada mail.python.org/pipermail/python-dev/2005-September/056677.html Bay Brown'un ifade ettiği hız ve komplikasyon hakkında daha fazla ayrıntı veriyor.
rajesh

62

Python'un diğer diller gibi blokları yoktur (C / C ++ veya Java gibi). Bu nedenle, Python'daki kapsam belirleme birimi bir işlevdir.


3
Kafam karıştı - Python'un döngüler için işlevlerin kapsamlandırıldığı şekilde kapsamasını engelleyen nedir?
chimeracoder

36
Gerçekten doğru değil, sadece dilbilgisi çılgınca gitmiyor. ( docs.python.org/reference/… ) "Bir blok, bir birim olarak yürütülen bir Python program metni parçasıdır. Aşağıdakiler bloklardır: bir modül, bir fonksiyon gövdesi ve bir sınıf tanımı ..."
Jeremy Kahverengi

1
@thebackhand, hiçbir şey. Sadece gereksiz görüldü.
habnabit

@Jeremy Brown - gerçekten. İyi not.
atzz

6
@thebackhand - bloklu dillerde kapsam belirleme fordöngüleri genel prensibin doğal bir uzantısıdır. Python'da özel bir durum olmalı ve zorlayıcı faydaları olmadıkça özel durumlardan kaçınılmalıdır.
atzz

39

Bunun için gerçekten yararlı bir durum, kullanırken enumerateve sonunda toplam sayımı istediğinizde:

for count, x in enumerate(someiterator, start=1):
    dosomething(count, x)
print "I did something {0} times".format(count)

Bu gerekli mi? Hayýr. Ama, kesinlikle uygun.

Dikkat edilmesi gereken başka bir şey: Python 2'de liste kavrayışındaki değişkenler de sızdırıldı:

>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> x
9

Ancak, Python 3 için de aynı şey geçerli değildir.


4
Bunu muhtemelen elsemaddede yapabilirdiniz, yani. else: print "I did something {0} times".format(count)- yerel kapsamdan önce (Python'da mevcut değil) kaybolmadan önce
Nas Banov

3
Python 3'te sadece ikinci örnek çalışmıyor, değil mi? Birincisi hala öyle mi? Python 3'ten neden kaldırıldığına dair notlar?
endolith

7
sayım için, numaralandırılan öğe (a, başlangıç ​​= 1): # varsayılan dizin sıfırdan
Tao Zhang

3
İlk örnek, iyi bir kullanım örneği olmaktan ziyade, bu kapsam belirleme kuralının tehlikeli olduğuna ve buna güvenilmemesi gerektiğine dair kanıt gibi görünmektedir. Boşsa ne olur someiterator?
maksimum

1
@Nas elseBu durumda bir cümle kullanılabilse de, döngü gövdesi breakerken olabileceğinden genel olarak çalışmaz .
jamesdlin

2

Döngüde bir break ifadeniz varsa (ve yineleme değerini daha sonra kullanmak, belki de bir şeyleri indekslemek veya bir durum vermek için) istiyorsanız, size bir kod satırı ve bir atama kaydeder, bu nedenle bir kolaylık vardır.


1

Python için birincil etkilerin biri ABC , yeni başlayanlar için programlama kavramları öğretmek için Hollanda'da geliştirilen bir dil. Python'un yaratıcısı Guido van Rossum, 1980'lerde birkaç yıl ABC'de çalıştı. ABC hakkında neredeyse hiçbir şey bilmiyorum, ama yeni başlayanlar için tasarlandığından, sanırım erken BASIC'ler gibi sınırlı sayıda kapsamı olmalı.


-1

Yeni başlayanlar için, değişkenler döngüler için yerel olsaydı, bu döngüler çoğu gerçek dünya programlaması için işe yaramazdı.

Mevcut durumda:

# Sum the values 0..9
total = 0
for foo in xrange(10):
    total = total + foo
print total

verim 45. Şimdi, Python'da atamanın nasıl çalıştığını düşünün. Döngü değişkenleri kesinlikle yerel olsaydı:

# Sum the values 0..9?
total = 0
for foo in xrange(10):
    # Create a new integer object with value "total + foo" and bind it to a new
    # loop-local variable named "total".
    total = total + foo
print total

verim 0nedeniyle, totalatama sonra döngü içinde aynı değişken değildir totaldöngü dışında. Bu optimal veya beklenen bir davranış değildir.


5
Soruyu cevaplamamak. OP toplam değil foo hakkında soruyordu (veya örneklerinde bar).
James Bradbury

6
@ JamesBradbury totalve foohala OP'nin senaryosunda döngü-yerel bağlamaları olurdu ve mantık aynı.
Kirk Strauser

2
OP: "Neden 'bar' ın döngü dışında erişilebilir olmasının gerekli olabileceğini anlayabiliyorum (aksi takdirde döngüler çok sınırlı işlevselliğe sahip olurdu). Anlamadığım şey, kontrol değişkeninin neden kalması gerektiğidir döngü çıktıktan sonra kapsam dahilinde. " (Vurgu madeni)
James Bradbury

2
@JamesBradbury Haklı olabilirsiniz, ancak bunu üç yıl önce yanıtladım ve muhtemelen şimdi tartışmaya değmez.
Kirk Strauser
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.