Nie było dokładnej odpowiedzi dotyczącej czasu Python3, więc udzieliłem odpowiedzi tutaj. Większość tego, co tu opisano, szczegółowo opisano w 4.2.2 Rozdzielczość nazw dokumentacji Python 3.
Jak podano w innych odpowiedziach, istnieją 4 podstawowe zakresy, LEGB, dla lokalnego, zamkniętego, globalnego i wbudowanego. Oprócz nich istnieje specjalny zakres, ciało klasy , które nie obejmuje zakresu obejmującego metody zdefiniowane w klasie; wszelkie przypisania w ciele klasy powodują, że zmienna jest odtąd związana w ciele klasy.
Zwłaszcza brak instrukcji blokowej poza tym def
i class
tworzenie zmiennego zakresu. W Pythonie 2 obsługa list nie tworzy zakresu zmiennych, jednak w Pythonie 3 zmienna pętli w ramach list jest tworzona w nowym zakresie.
Aby zademonstrować osobliwości ciała klasowego
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)
Zatem, inaczej niż w ciele funkcji, można ponownie przypisać zmienną do tej samej nazwy w ciele klasy, aby uzyskać zmienną klasy o tej samej nazwie; dalsze wyszukiwania tej nazwy rozstrzygają zamiast tego zmienną klasy.
Jedną z większych niespodzianek dla wielu nowych użytkowników Pythona jest to, że for
pętla nie tworzy zakresu zmiennego. W Pythonie 2 wyrażenia listowe również nie tworzą zakresu (podczas gdy generatory i wyrażenia dyktują!). Zamiast tego przeciekają wartość w funkcji lub zasięgu globalnym:
>>> [ i for i in range(5) ]
>>> i
4
Wyjaśnienia mogą być używane jako sprytny (lub okropny, jeśli chcesz) sposób modyfikowania zmiennych w wyrażeniach lambda w Pythonie 2 - wyrażenie lambda tworzy zakres zmiennych, podobnie jak def
instrukcja, ale w lambda żadne instrukcje nie są dozwolone. Przypisanie będące instrukcją w Pythonie oznacza, że żadne przypisania zmiennych w lambda nie są dozwolone, ale rozumienie listy jest wyrażeniem ...
To zachowanie zostało naprawione w Pythonie 3 - brak wyrażeń związanych ze zrozumieniem lub zmiennych wyciekających z generatorów.
Globalny naprawdę oznacza zakres modułu; głównym modułem Pythona jest __main__
; wszystkie importowane moduły są dostępne poprzez sys.modules
zmienną; aby uzyskać dostęp do __main__
jednego z nich sys.modules['__main__']
, lub import __main__
; dostęp do nich i przypisywanie atrybutów jest całkowicie do przyjęcia; pojawią się jako zmienne w globalnym zakresie modułu głównego.
Jeśli nazwa zostanie kiedykolwiek przypisana w bieżącym zakresie (z wyjątkiem zakresu klasy), zostanie uznana za należącą do tego zakresu, w przeciwnym razie zostanie uznana za należącą do dowolnego obejmującego zakresu, który przypisuje zmiennej (może nie zostać przypisana jeszcze, albo wcale), czy wreszcie zasięg globalny. Jeśli zmienna jest uważana za lokalną, ale nie jest jeszcze ustawiona lub została usunięta, odczyt wartości zmiennej spowoduje UnboundLocalError
, co jest podklasą 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()
Zakres może zadeklarować, że wyraźnie chce zmodyfikować zmienną globalną (zakres modułu) za pomocą słowa kluczowego global:
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
Jest to również możliwe, nawet jeśli został ukryty w zakresie:
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
W Pythonie 2 nie ma łatwego sposobu na modyfikację wartości w otaczającym zakresie; zwykle jest to symulowane przez wartość zmienną, taką jak lista o długości 1:
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
Jednak w Pythonie 3 nonlocal
przychodzi na ratunek:
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
Dokumentacja mówi, że
Nazwy wymienione w instrukcji nielokalnej, w przeciwieństwie do tych wymienionych w instrukcji globalnej, muszą odnosić się do wcześniej istniejących powiązań w zakresie obejmującym (zakresu, w którym należy utworzyć nowe powiązanie, nie można jednoznacznie określić).
tzn. nonlocal
zawsze odnosi się do najbardziej wewnętrznego zewnętrznego zakresu nieglobalnego, w którym nazwa została powiązana (tj. przypisana, w tym używana jako for
zmienna docelowa, w with
klauzuli lub jako parametr funkcji).
Każda zmienna, która nie jest uważana za lokalną dla bieżącego zakresu lub dowolnego obejmującego zakresu, jest zmienną globalną. Globalna nazwa znajduje się w globalnym słowniku modułu; jeśli nie zostanie znaleziony, globalny jest następnie sprawdzany z wbudowanego modułu; nazwa modułu została zmieniona z python 2 na python 3; tak było w Pythonie 2, __builtin__
a teraz w Pythonie 3 builtins
. Jeśli przypiszesz atrybut wbudowanemu modułowi, będzie on później widoczny dla dowolnego modułu jako czytelna zmienna globalna, chyba że moduł ten ocienia je własną zmienną globalną o tej samej nazwie.
Przydatny może być także odczyt wbudowanego modułu; załóżmy, że chcesz funkcji drukowania w stylu Pythona 3 w niektórych częściach pliku, ale inne części pliku nadal używają print
instrukcji. W Pythonie 2.6-2.7 można uzyskać funkcję Python 3 za print
pomocą:
import __builtin__
print3 = __builtin__.__dict__['print']
from __future__ import print_function
Faktycznie nie importuje się print
nigdzie funkcji w Pythonie 2 - zamiast po prostu wyłącza zasady analizowania na print
rachunku w bieżącym module obsługi print
jak każdy inny identyfikator zmiennej, a tym samym pozwalając print
funkcja być spojrzał w builtins.