Python yerel olmayan bildirimi


341

Python nonlocaldeyimi ne yapar (Python 3.0 ve sonraki sürümlerde)?

Resmi Python web sitesinde herhangi bir belge yok ve help("nonlocal")çalışmıyor.



18
Yerel olmayanlar için resmi Python web sitesi belgeleri: docs.python.org/3/reference/… (bu belge Python 3.0'dan beri mevcuttur, bu nedenle OP'nin resmi bir belge olmadığı iddiası sadece yanlıştı)
wkschwartz

3
"There is no documentation for nonlocal".Aslında, help(keyword_in_string)Python 3 ve üzeri belgeler için yapabilirsiniz
ytpillai

10
Adil olmak gerekirse resmi dokümanlar bu konuda emmek. Seçilen yanıtın örneği işleri çok açık hale getirir, bu da bunu değerli bir soru haline getirir.
Çılgın Fizikçi

Resmi Python eğitimde bir var kapsamları ve ad kavramının iyi açıklama bir ile güzel örnek .
jammon

Yanıtlar:


473

Bunu kullanmadan karşılaştırın nonlocal:

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

Bunu kullanarak nonlocal, nerede inner()'s xşimdi de outer()' s x:

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

Kullanacak globalolsaydık x, düzgün "küresel" değere bağlanırdı :

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

32
Küresel x'ten farkı nedir?
ooboo

52
Çok benzer - ancak dış x'in örnekte global olmadığını, bunun yerine dış fonksiyonda tanımlandığını unutmayın.
Anon

3
@Dustin - Aslında, A ve x alt sınıfında B özniteliğine sahip A sınıfınız varsa, B'den X'e Ax
Anon

2
İç fonksiyonlar tanımlanırken kod kolayca girintili olur ve 79 karakterlik PEP8 önerisini ihlal eder. Bu sorunu aşmanın bir yolu var mı? Bir iç fonksiyon bir şekilde dış fonksiyonun dışına yerleştirilebilir mi? Sorunun aptalca geldiğini biliyorum, ama ciddiyim.
tommy.carstensen

3
@ tommy.carstensen işlevi daha üst düzey işlevlerin güzelliği olan bir argüman olarak geçirebilirsiniz. Ayrıca fonksiyonel programlamada buna kompozisyon denir, python saf bir FP dili değildir, ancak kesinlikle bir özellik ile oynayabilirsiniz (jeneratörler, yüksek dereceli fonksiyonlar bazı örneklerdir)
superuseroi

90

Kısacası, bir dış (ancak global olmayan) kapsamdaki bir değişkene değer atamanıza izin verir. Tüm kanlı ayrıntılar için PEP 3104'e bakın.


41

"Python yerel olmayan" için yapılan bir Google araması , ifadenin arkasındaki sözdizimini ve mantığı tam olarak açıklayan Teklif PEP 3104'ü getirdi . Kısacası, tam olarak aynı şekilde çalışır.global işlev için ne küresel ne de yerel değişkenleri ifade etmek için kullanılması dışında ifadeyle çalışır.

İşte bununla neler yapabileceğinizin kısa bir örneği. Sayaç üreteci bunu kullanmak için yeniden yazılabilir, böylece daha çok kapaklı dillerin deyimlerine benzeyebilir.

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

Açıkçası, bunu bir jeneratör olarak yazabilirsiniz, örneğin:

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

Ancak bu mükemmel deyimsel python olsa da, ilk versiyonun yeni başlayanlar için biraz daha açık olacağı anlaşılıyor. Jeneratörleri uygun şekilde kullanmak, döndürülen işlevi çağırarak ortak bir karışıklık noktasıdır. İlk sürüm açıkça bir işlev döndürür.


1
'Global' anahtar kelimesinin yaptığı şeyden emindim - bu ada sahip bir değişkene ulaşıncaya kadar daha yüksek ortamlar oluşturur. bir x değişkeni modül düzeyinde, bir sınıfın içinde, daha sonra bu sınıfın içindeki bir fonksiyonda ve daha sonra bu fonksiyonun bir iç fonksiyonunda ilan edilebilir - hangi x'e atıfta bulunacağını nasıl bilebilir?
ooboo

7
global ile ilgili şey, sadece global değişkenler için çalışmasıdır. çevreleyen, küresel olmayan bir kapsamdaki değişkenleri göremez.
SingleNegationElimination

Make_counter denedim - ancak bir jeneratör ancak bir işlev döndürmez. daha sonra üzerinde yineleme olabilir bir jeneratör dönmek için bir yolu var mı?
Dejell

@Dejel: Bu örnek nonlocalPython'daki ifadeyi açıklamaya yöneliktir ; Doğal sayılar dizisi istiyorsanız, python deyimi aslındaitertools.count()
SingleNegationElimination

Verimi olduğu gibi bir jeneratörü geri döndürme yeteneğini demo etmek istiyorum - verim aslında bir jeneratör döndürür. Benim fikrim verimi kullanmak değil, belki de yerel olmayan veya başka bir çözüm kullanmaktır
Dejell

15

@ooboo:

Kaynak koddaki referans noktasına "en yakın" olanı alır. Buna "Lexical Scoping" denir ve 40 yıldan uzun bir süredir standarttır.

Python'un sınıf üyeleri gerçekten adlı bir sözlükte __dict__ ve asla sözcüksel kapsam belirleme ile ulaşılamaz.

Belirtmez nonlocalancak yaparsanız x = 7, yeni bir yerel değişken "x" oluşturur. Belirtirseniz nonlocal, "en yakın" "x" i bulur ve buna atar. Belirtirseniznonlocal ve "x" yoksa, size bir hata mesajı verir.

Anahtar kelime globalbenim için her zaman garip görünüyordu, çünkü en dıştaki hariç tüm diğer "x" değerlerini görmezden gelecektir. Tuhaf.


14

yardımı ( 'yerel olmayan') nonlocaldeyimi


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

nonlocalİfadesi en yakın kapsayan kapsamında önceden bağlanmış değişkenlere başvurmak için listelenen tanımlayıcıları neden olur. Bağlama için varsayılan davranış ilk önce yerel ad alanında arama yapmak olduğundan önemlidir. İfade, kapsüllenmiş kodun global (modül) kapsamın yanı sıra yerel kapsam dışındaki değişkenleri yeniden hatırlamasına izin verir.

Bir nonlocalifadede listelenen isimler , bir global , bir ek kapsamda önceden var olan bağlara atıfta bulunmalıdır (yeni bir bağlamanın oluşturulması gereken kapsam kesin olarak belirlenemez).

İfadede listelenen isimler nonlocal, yerel kapsamda önceden var olan ciltlerle çarpışmamalıdır.

Ayrıca bakınız:

PEP 3104 - Dış Kapsamlardaki Adlara Erişim İfadenin
belirtimi nonlocal.

İlgili yardım konuları: global, NAMESPACES

Kaynak: Python Dil Başvurusu


11
Her gün yeni bir şeyler öğrenin. help()Anahtar kelimeler üzerinde kullanabileceğiniz hakkında hiçbir fikrim yoktu (ve şimdi zihnim patladı: help()hiçbir argüman ile interaktif gider ).
Erik Youngren

6

Python 3 Referansından Alıntı :

Yerel olmayan ifade, listelenen tanımlayıcıların globaller hariç en yakın çevreleme kapsamındaki önceden bağlanmış değişkenlere başvurmasına neden olur.

Referansta belirtildiği gibi, birkaç iç içe fonksiyon durumunda, sadece en yakın çevreleme fonksiyonundaki değişken değiştirilir:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        x = 2
        innermost()
        if x == 3: print('Inner x has been modified')

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Inner x has been modified

"En yakın" değişken birkaç seviye uzakta olabilir:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Outer x has been modified

Ancak küresel bir değişken olamaz:

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    inner()

x = 0
outer()
if x == 3: print('Global x has been modified')

# SyntaxError: no binding for nonlocal 'x' found

3
a = 0    #1. global variable with respect to every function in program

def f():
    a = 0          #2. nonlocal with respect to function g
    def g():
        nonlocal a
        a=a+1
        print("The value of 'a' using nonlocal is ", a)
    def h():
        global a               #3. using global variable
        a=a+5
        print("The value of a using global is ", a)
    def i():
        a = 0              #4. variable separated from all others
        print("The value of 'a' inside a function is ", a)

    g()
    h()
    i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)

2

"Yerel olmayan" ifadeye ilişkin kişisel anlayışım (ve genel olarak Python ve Programlama'da yeni olduğum için özür dilerim), "yerel olmayan" kodun gövdesinden ziyade yinelenen işlevlerde Global işlevselliği kullanmanın bir yoludur . İsterseniz işlevler arasında genel bir ifade.


0

'yerel olmayan' iç fonksiyonlarla (yani iç içe iç fonksiyonlar) dış ana fonksiyonun belirli bir değişkeni için okuma ve yazma izni alabilirsiniz . Yerel olmayan sadece iç fonksiyonlarda kullanılabilir, örneğin:

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)
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.