Python'da kapsam ve ad alanları arasındaki ilişki nedir?


12

Birçok kaynakta "kapsam" ve "ad alanları" ifadelerinin birbirinin yerine kullanıldığını fark ettim , bu da farklı şeyler ifade ettiklerinden biraz kafa karıştırıcı görünüyor.

  • Kapsam, kodun bir adın bulunduğu bölgesini tanımlar.
  • LEGB kuralı, adların aranma biçimini tanımlar.
  • Ad alanı, isimleri aradığınız bir yerdir.

Sonra okudum:

  • "İsimler, atandıkları yere göre bir ad alanına bağlanır ..." (bu, sözcüksel kapsam belirleme kapsamlarıyla ilgili bir anlaşma olduğuna inanıyorum).
  • msgstr "işlevler programlarınıza fazladan bir ad alanı katmanı ekler" [ ref. ] (fazladan yerel bir kapsam eklemiyorlar mı?)
  • msgstr "bir işlev tanımına atanan tüm adlar yerel kapsama (işlev çağrısıyla ilişkilendirilmiş ad alanı) konur."
  • "global scope — yani modül dosyasının en üst düzeyinde oluşturulan (atanan) değişkenlerin canlı olduğu bir ad alanı."

* Tüm alıntılar python 5. baskı ch17 öğrenmekten

Python'daki ad alanları kapsamların uygulanma şekli midir? Aynı şey mi? Biri beni aydınlatabilir mi?


1
Alıntılar için referanslar verebilir misiniz - birini bulabilirim, ama diğerini değil.
jonrsharpe

1
Ad alanları yalnızca bir tür kapsamdır. Bkz. Stackoverflow.com/questions/291978/…
Robert Harvey

Yanıtlar:


16

Bir ad değerlerine (dizeleri gibi) isimlerini haritalama, bir sözlük olduğunu. Ödev yaptığınızda, örneğin a = 1bir ad alanını değiştiriyorsunuzdur. Bir referans yaptığınızda print(a), Python, adı anahtar olan bir tanesini bulmaya çalışmak için bir ad alanları listesine bakar.

Bir kapsam , hangi ad alanlarına hangi sırayla bakılacağını tanımlar. Herhangi referans kapsamı her zaman yerel ad alanında başlar ve geçmeden önce, modülün genel ad alanını ulaşıncaya kadar dışa doğru hamle builtins(ad olduğu referanslar Python'un önceden tanımlanmış fonksiyonlar ve sabitler gibi rangeve getattr) çizginin sonu, .

Adında inner, adında genel bir işlevde iç içe geçmiş bir işleve sahip olduğunuzu outerve innerbir ad için başvuru içerdiğini düşünün . Python önce innerad alanına bakar . Ad orada değilse, Python outerad alanına bakar . Bu başarısız olursa, Python modülün globalad alanını, ardından ad alanını dener ve builtinsonunda NameErrorisim bulunamazsa bir a atar .

Bir xfonksiyonun ad alanında olduğunu söylediğimizde , fonksiyonun içinde yerel olarak orada tanımlandığını kastediyoruz. xFonksiyonun kapsamında olduğunu söylediğimizde , xya fonksiyonun ad alanında ya da fonksiyonun ad alanının içine yerleştirilmiş olduğu dış ad alanlarının herhangi birinde olduğunu kastediyoruz .

Bir işlev tanımladığınızda, yeni bir ad alanı ve yeni bir kapsam oluşturursunuz. İsim alanı yeni, yerel isim karmasıdır. Kapsam, yeni ad alanında başlayan, daha sonra herhangi bir dış ad alanında (dış kapsamlar), global ad alanına (global kapsam) ve yerleşiklere kadar giden zımni ad alanları zinciridir.

Terimler neredeyse birbirinin yerine kullanılabilir, ancak bunun nedeni aynı anlama gelmesi değildir; çünkü ima ettikleri şeyle çok örtüşüyorlar.


3
"Terimler neredeyse birbirinin yerine kullanılabilir, ancak bunun nedeni aynı anlama geldiği için değil; ima ettikleri şeyle çok fazla örtüşmeleri."
Nikos

2
Bu cevap ruh olarak doğrudur, ancak ayrıntılı olarak yanlıştır. Python'daki sınıflar yeni bir ad alanı sunmaz, bu nedenle sınıf özniteliklerinin sınıf adıyla nitelendirilmesi ve örnek özniteliklerinin örnek adıyla nitelendirilmesi gerekir. Python'da içten dışa isim alanı seviyeleri Yerel, Çevreleyen, Global ve Yerleşik'tir. Bir sınıf bu seviyelerin herhangi birinde tanımlanabilir, ancak bir sınıfın üyeleri her zaman kalifiye olmalıdır.
Rob Smallshire

Haklısın. Sınıflar söylediğim gibi çalışmıyor. Bir işlev gibi sözcüksel bir kapsam oluşturduklarını düşünüyordum ama yapmıyorlar. Lütfen zamanınız varsa cevabı güncelleyin, aksi takdirde bir noktada yapacağım. Teşekkürler.
Carl Smith

1
+1 Bu tür inceliği çok ekonomik bir şekilde kapsayan parlak cevap. Bunu çok faydalı buldum, teşekkürler!
Arayan

1
"Ad alanı adı, değer çiftleri, bir Python sözlük gibi bir çok karma olan" - Ben ad eminim vardır piton sözlükleri olarak depolanır. Örneğin, sözlüğü doğrudan nesneleri ve adları bağlamak için değiştirmenize izin veren globals () öğesini çağırarak genel ad alanını düzenleyebilirsiniz: örneğin globals () [name] = "object". Aksi takdirde büyük cevap.
Evan Rosica

4

Burada Python ad alanlarında mükemmel bir makale var . Kapsamlar ve ad alanları arasındaki referans hakkındaki sorunuzu yanıtlayacak ilgili bölümü alıntılamak için:

Kapsam, bir programın önek olmadan ad alanına erişilebildiği bir bölgeyi ifade eder.

Örneğin, basit bir kalıp haddeleme programını düşünün:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll kendi ad alanına sahiptir , ancak modülün ad alanındaki adlar da kapsam dahilindedir .


@CarlSmith, erken Python belgelerinin aynı şeyi söylediğini belirtiyor: "Kapsam, bir ad alanının doğrudan erişilebilir olduğu bir Python programının metinsel bir bölgesidir." Doğrudan erişilebilir '', burada bir ad için niteliksiz bir referansın adı bulmaya çalıştığı anlamına gelir. "
jonrsharpe

@CarlSmith yerel olmayan / çevreleyen kapsamın dışında, bu çok değişti mi? Sanırım aynı şeyi söylüyoruz - bir ad alanı isimleri ve değerleri içerir ve kapsam size hangi ad alanlarına erişilebilir olduğunu söyler.
jonrsharpe

Eski yorumlarımı sildim.
Carl Smith
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.