Python3 zamanıyla ilgili tam bir cevap yoktu, bu yüzden burada bir cevap verdim. Burada açıklananların çoğu , Python 3 belgelerinin adlarının 4.2.2 çözümlenmesinde ayrıntılı olarak açıklanmıştır .
Diğer cevaplarda belirtildiği gibi, Yerel, Çevreleyen, Küresel ve Yerleşik için LEGB olmak üzere 4 temel kapsam vardır. Bunlara ek olarak, sınıf içinde tanımlanan yöntemler için kapalı bir kapsam içermeyen özel bir kapsam, sınıf gövdesi vardır; sınıf gövdesindeki tüm ödevler, değişkeni sınıf gövdesinde bağlı hale getirir.
Özellikle hiçbir blok deyimi, yanında def
ve class
değişken bir kapsam oluşturun. Python 2'de bir liste kavraması değişken bir kapsam oluşturmaz, ancak Python 3'te liste kavramaları içindeki döngü değişkeni yeni bir kapsamda oluşturulur.
Sınıf bedeninin özelliklerini göstermek
x = 0
class X(object):
y = x
x = x + 1 # x is now a variable
z = x
def method(self):
print(self.x) # -> 1
print(x) # -> 0, the global x
print(y) # -> NameError: global name 'y' is not defined
inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)
Böylece işlev gövdesinden farklı olarak, aynı ada sahip bir sınıf değişkeni elde etmek için değişkeni sınıf gövdesinde aynı ada yeniden atayabilirsiniz; bu isimdeki diğer aramalar sınıf değişkenine çözümlenir.
Python'a birçok yeni gelen için daha büyük sürprizlerden biri, bir for
döngünün değişken bir kapsam yaratmamasıdır. Python 2'de liste kavrayışları da bir kapsam oluşturmaz (jeneratörler ve diksiyon kavrayışları yapar!) Bunun yerine işlevdeki veya global kapsamdaki değeri sızdırırlar:
>>> [ i for i in range(5) ]
>>> i
4
Anlayışlar Python 2'de lambda ifadeleri içinde değiştirilebilir değişkenler oluşturmanın kurnaz (veya yapacaksanız korkunç) bir yol olarak kullanılabilir - lambda ifadesi, ifade gibi değişken bir kapsam oluşturur def
, ancak lambda içinde hiçbir ifadeye izin verilmez. Python'da bir deyim olarak atama, lambda'da değişken atamalara izin verilmediği anlamına gelir, ancak liste kavraması bir ifadedir ...
Bu davranış Python 3'te giderilmiştir - anlama ifadeleri veya jeneratör kaçak değişkenleri yoktur.
Küresel, modülün kapsamı anlamına gelir; ana python modülü __main__
; içe aktarılan tüm modüllere sys.modules
değişken üzerinden erişilebilir ; __main__
birine erişmek için kullanabilirsiniz sys.modules['__main__']
, veya import __main__
; orada özniteliklere erişmek ve atamak tamamen kabul edilebilir; ana modülün küresel kapsamında değişkenler olarak görüneceklerdir.
Geçerli kapsamda (sınıf kapsamı hariç) bir ad atanmışsa, bu kapsama ait olduğu kabul edilir, aksi takdirde değişkene atanan herhangi bir kapalı kapsama ait olduğu kabul edilir (atanmamış olabilir henüz veya hiç değil) veya son olarak küresel kapsam. Değişken yerel olarak kabul edilir, ancak henüz ayarlanmamışsa veya silinmişse, değişken değerinin okunması UnboundLocalError
bir alt sınıftır NameError
.
x = 5
def foobar():
print(x) # causes UnboundLocalError!
x += 1 # because assignment here makes x a local variable within the function
# call the function
foobar()
Kapsam, global (modül kapsamı) değişkenini global anahtar kelimeyle açıkça değiştirmek istediğini bildirebilir:
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
Bu, kapalı kapsamda gölgeli olsa bile mümkündür:
x = 5
y = 13
def make_closure():
x = 42
y = 911
def func():
global x # sees the global value
print(x, y)
x += 1
return func
func = make_closure()
func() # -> 5 911
print(x, y) # -> 6 13
Python 2'de, kapalı alandaki değeri değiştirmenin kolay bir yolu yoktur; genellikle bu, uzunluğu 1 olan bir liste gibi değiştirilebilir bir değere sahip olarak simüle edilir:
def make_closure():
value = [0]
def get_next_value():
value[0] += 1
return value[0]
return get_next_value
get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2
Ancak python 3'te nonlocal
kurtarmaya gelir:
def make_closure():
value = 0
def get_next_value():
nonlocal value
value += 1
return value
return get_next_value
get_next = make_closure() # identical behavior to the previous example.
nonlocal
Dokümantasyon söylüyor
Yerel olmayan bir deyimde listelenen adlar, genel bir deyimde listelenenlerden farklı olarak, kapalı bir kapsamda önceden var olan bağlamaları belirtmelidir (yeni bir bağlamanın oluşturulması gereken kapsam kesin olarak belirlenemez).
yani nonlocal
her zaman adın bağlandığı en içteki dış küresel olmayan kapsamı ifade eder (yani for
, with
yan tümcedeki veya bir işlev parametresi olarak hedef değişken olarak kullanılanlar dahil ).
Geçerli kapsamda veya herhangi bir kapalı kapsamda yerel olarak kabul edilmeyen herhangi bir değişken genel bir değişkendir. Modül global sözlüğünde bir genel ad aranır; bulunamazsa, global yerleşik modülden aranır; modülün adı python 2'den python 3'e değiştirildi; python 2'de __builtin__
ve python 3'te şimdi denir builtins
. Yerleşik modülün bir özniteliğine atarsanız, daha sonra herhangi bir modül tarafından okunabilir genel değişken olarak görünür, ancak bu modül aynı ada sahip kendi genel değişkeniyle gölgelendirmezse.
Yerleşik modülü okumak da yararlı olabilir; Dosyanın bazı bölümlerinde python 3 stili yazdırma işlevini istediğinizi, ancak dosyanın diğer bölümlerinin yine de print
ifadeyi kullandığını varsayalım . Python 2.6-2.7'de Python 3'ü elde edebilirsinizprint
işlevini :
import __builtin__
print3 = __builtin__.__dict__['print']
from __future__ import print_function
Aslında almaz print
Python 2'de fonksiyon hiçbir yerinde - yerine sadece için ayrıştırma kuralları devre dışı bırakır print
taşıma, cari modülünde açıklamada print
başka değişken tanımlayıcı gibi ve böylece izin print
fonksiyon yerleşikleri buradan takip edilebilir.