2009-08-11 12 views
174

Co robi instrukcja Python nonlocal (w Pythonie 3.0 i nowszych)?Python Nonlocal oświadczenie

Nie ma dokumentacji na oficjalnej stronie Pythona i nie działa też help("nonlocal").

+4

Spójrz na to pytanie: http://stackoverflow.com/questions/1414304/local-functions-in -python –

+12

Oto oficjalna dokumentacja Pythona dla stron nielokalnych: http://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement (ta dokumentacja jest dostępna od wersji Python 3.0, więc asercja OP że oficjalna dokumentacja nie była po prostu błędna) – wkschwartz

+3

'' Nie istnieje żadna dokumentacja dla nielokalnego "." Właściwie możesz zrobić 'help (keyword_in_string)' dla dokumentacji w Pythonie 3 i powyżej – ytpillai

Odpowiedz

254

Porównaj to bez użycia 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 

Aby to zrobić, używając nonlocal, gdzie inner() 's x jest teraz również 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 

Gdybyśmy mieli użyć global, to wiążą x do odpowiednio "globalnej" wartości:

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 
+25

Czym różni się od globalnego x? – ooboo

+36

Jest bardzo podobny - ale zauważ, że zewnętrzny x nie jest globalny w tym przykładzie, ale jest zdefiniowany w zewnętrznej funkcji. – Anon

+0

dzięki czemu można tworzyć wewnętrzne klasy odwołujące się do zewnętrznych zmiennych, takich jak java? –

64

W skrócie umożliwia przypisanie wartości do zmiennej w zewnętrznym (ale nie globalnym) zakresie. Zobacz PEP 3104, aby poznać wszystkie szczegóły.

29

Wyszukiwarka google "python nonlocal" pojawiła się w propozycji, PEP 3104, która w pełni opisuje składnię i rozumowanie instrukcji. krótko mówiąc, działa dokładnie tak samo, jak instrukcja global, z tą różnicą, że jest używana do oznaczania zmiennych, które nie są ani globalne, ani lokalne dla funkcji.

Oto krótki przykład tego, co można z tym zrobić. Licznik może zostać przepisany w celu użycia tego, aby wyglądał bardziej jak idiomy języków z zamknięciami.

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

Oczywiście, można napisać to jako generator, jak:

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

Ale jednocześnie jest doskonale idiomatycznych python, wydaje się, że pierwsza wersja będzie nieco bardziej oczywiste dla początkujących . Właściwe używanie generatorów, przez wywoływanie zwróconej funkcji, jest powszechnym punktem dezorientacji. Pierwsza wersja jawnie zwraca funkcję.

+1

Byłem pewien, że to właśnie robi słowo kluczowe "globalny" - działa na wyższe środowiska, dopóki nie osiągnie zmiennej o tej nazwie.zmienna x może być zadeklarowana na poziomie modułu, wewnątrz klasy, a następnie osobno w funkcji wewnątrz tej klasy, a następnie w wewnętrznej funkcji tej funkcji - skąd wie, do którego x się odwoływać? – ooboo

+4

Rzecz o globalności polega na tym, że działa ona tylko dla zmiennych globalnych. nie może zobaczyć zmiennych w otaczającym, nienamalnym zakresie. – SingleNegationElimination

+0

Próbowałem make_counter - jednak nie zwraca on generatora, ale funkcję. czy istnieje sposób na zwrócenie generatora, aby później mógłbym go powtórzyć? – Dejell

11

@ooboo:

przybiera jedną "najbliżej" do punktu odniesienia w kodzie źródłowym. Nazywa się to "Schematem leksykalnym" i jest standardem od ponad 40 lat.

Członkowie klasy Pythona naprawdę znajdują się w słowniku o nazwie __dict__ i nigdy nie zostaną osiągnięte przez zakresy leksykalne.

Jeśli nie podasz nonlocal, ale zrobisz x = 7, utworzy on nową zmienną lokalną "x". Jeśli podasz nonlocal, znajdziesz "najbliższy" "x" i przypiszesz do tego. Jeśli podasz nonlocal i nie ma "x", pojawi się komunikat o błędzie.

Słowo kluczowe global zawsze wydawało mi się dziwne, ponieważ z radością zignoruje wszystkie pozostałe "x", z wyjątkiem najbardziej oddalonego. Dziwne.

2

Moje osobiste zrozumienie "nielokalnego" stwierdzenia (i wybaczcie, że jestem nowy w Pythonie i Programowaniu w ogóle) jest to, że "nielokalny" jest sposobem na wykorzystanie Globalnej funkcjonalności w ramach iterowanych funkcji, a nie ciała samego kodu. Globalne oświadczenie między funkcjami, jeśli zechcesz.

13

pomocy ('nielokalna') nonlocal oświadczenie


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

Oświadczenie nonlocal powoduje wymienione identyfikatory odnoszą się do wcześniej związany zmiennych w najbliższym zakresu obejmującego. Jest to ważne, ponieważ domyślnym zachowaniem dla wiązania jest najpierw przeszukiwanie lokalnej przestrzeni nazw . Instrukcja umożliwia kodowanie enkapsulowane do zmiennych rebind poza zasięgiem lokalnym poza zasięgiem globalnym (moduł).

Nazwy wymienione w nonlocal oświadczenie, w przeciwieństwie do tych wymienionych w global oświadczenia, musi odnosić się do wcześniej istniejących powiązań w załączając zakres (zakres, w którym nowy wiążący powinien być utworzony nie można ustalić w sposób jednoznaczny) .

Nazwy wymienione w oświadczeniu nonlocal nie mogą kolidować z istniejącymi powiązaniami istniejącymi w zasięgu lokalnym.

Zobacz także:

PEP 3104 - Dostęp do Nazewnictwa w Outer zakresów
Specyfikacja rachunku nonlocal.

Pokrewne tematy Pomocy: globalne, Przestrzenie nazw

Źródło: Python Language Reference

+5

Dowiedz się czegoś nowego każdego dnia. Nie miałem pojęcia, że ​​możesz użyć słowa 'help()' na słowach kluczowych (a teraz mój umysł jest przepalony: 'help()' bez argumentów idzie _interactive_). –

1
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)