Szukaj…


Składnia

  • globalne a, b, c
  • nielokalne a, b
  • x = coś # wiąże x
  • (x, y) = coś # wiąże xiy
  • x + = coś # wiąże x. Podobnie dla wszystkich innych „op =”
  • del x # wiąże x
  • dla x w czymś: # wiąże x
  • z czymś, co x: # wiąże x
  • oprócz Wyjątku jako ex: # wiąże ex wewnątrz bloku

Zmienne globalne

W Pythonie zmienne wewnątrz funkcji są uważane za lokalne wtedy i tylko wtedy, gdy pojawiają się po lewej stronie instrukcji przypisania lub w innym powiązaniu; w przeciwnym razie takie powiązanie jest sprawdzane w ramach funkcji obejmujących zakres globalny. Dzieje się tak nawet wtedy, gdy instrukcja przypisania nigdy nie jest wykonywana.

x = 'Hi'

def read_x():
    print(x)   # x is just referenced, therefore assumed global

read_x()       # prints Hi

def read_y():
    print(y)   # here y is just referenced, therefore assumed global

read_y()       # NameError: global name 'y' is not defined

def read_y():
    y = 'Hey'  # y appears in an assignment, therefore it's local
    print(y)   # will find the local y

read_y()       # prints Hey

def read_x_local_fail():
    if False:
        x = 'Hey'  # x appears in an assignment, therefore it's local
    print(x)   # will look for the _local_ z, which is not assigned, and will not be found

read_x_local_fail()   # UnboundLocalError: local variable 'x' referenced before assignment

Zwykle przypisanie w zakresie przesłania wszelkie zewnętrzne zmienne o tej samej nazwie:

x = 'Hi'

def change_local_x():
    x = 'Bye'
    print(x)
change_local_x()  # prints Bye
print(x)  # prints Hi

Deklaracja nazwy global oznacza, że dla pozostałej części zakresu wszelkie przypisania do nazwy będą miały miejsce na najwyższym poziomie modułu:

x = 'Hi'

def change_global_x():
    global x
    x = 'Bye'
    print(x)

change_global_x()  # prints Bye
print(x)  # prints Bye

global słowo kluczowe oznacza, że przypisania będą się odbywały na najwyższym poziomie modułu, a nie na najwyższym poziomie programu. Inne moduły nadal będą wymagały zwykłego dostępu kropkowego do zmiennych w module.

Podsumowując: aby wiedzieć, czy zmienna x jest lokalna dla funkcji, powinieneś przeczytać całą funkcję:

  1. jeśli znalazłeś global x , to x jest zmienną globalną
  2. Jeśli znalazłeś nonlocal x , x należy do funkcji zamykającej i nie jest ani lokalny, ani globalny
  3. Jeśli znalazłeś x = 5 lub for x in range(3) lub jakieś inne wiązanie, to x jest zmienną lokalną
  4. W przeciwnym razie x należy do zakresu obejmującego (zakres funkcji, zasięg globalny lub wbudowane)

Zmienne lokalne

Jeśli nazwa jest związana wewnątrz funkcji, domyślnie jest dostępna tylko w obrębie funkcji:

def foo():
    a = 5
    print(a) # ok

print(a) #  NameError: name 'a' is not defined

Konstrukty przepływ sterowania nie mają wpływu na zakres (z wyjątkiem except ), ale dostęp do zmiennej, która nie została jeszcze przypisana jest błąd:

def foo():
    if True: 
        a = 5
    print(a) # ok

b = 3
def bar():
    if False:
        b = 5
    print(b) # UnboundLocalError: local variable 'b' referenced before assignment

Typowymi operacjami wiązania są przypisania for pętli i rozszerzone przypisania, takie jak a += 5

Zmienne nielokalne

Python 3.x 3.0

Python 3 dodał nowe słowo kluczowe o nazwie nielokalne . Nielokalne słowo kluczowe dodaje przesłonięcie zakresu do zakresu wewnętrznego. Możesz przeczytać o tym wszystko w PEP 3104 . Najlepiej ilustruje to kilka przykładów kodu. Jednym z najczęstszych przykładów jest utworzenie funkcji, która może zwiększać:

def counter():
    num = 0
    def incrementer():
        num += 1
        return num
    return incrementer

Jeśli spróbujesz uruchomić ten kod, otrzymasz UnboundLocalError, ponieważ zmienna num jest wywoływana przed przypisaniem jej w najbardziej wewnętrznej funkcji. Dodajmy nielokalne do miksu:

def counter():
    num = 0
    def incrementer():
        nonlocal num
        num += 1
        return num
    return incrementer

c = counter()
c() # = 1
c() # = 2
c() # = 3

Zasadniczo nonlocal pozwolą ci przypisywać zmienne w zakresie zewnętrznym, ale nie w zakresie globalnym. Więc nie możesz użyć nonlocal w naszej funkcji counter ponieważ wówczas próbowałaby ona przypisać do zasięgu globalnego. Spróbuj, a szybko otrzymasz błąd SyntaxError . Zamiast tego należy użyć funkcji nonlocal w funkcji zagnieżdżonej.

(Należy zauważyć, że funkcja przedstawiona tutaj jest lepiej zaimplementowana za pomocą generatorów).

Wiążące wystąpienie

x = 5
x += 7
for x in iterable: pass    

Każda z powyższych instrukcji jest zjawiskiem wiążącym - x wiąże się z obiektem oznaczonym przez 5 . Jeśli to polecenie pojawi się wewnątrz funkcji, to x będzie domyślnie lokalne dla funkcji. Zobacz sekcję „Składnia”, aby uzyskać listę wiążących instrukcji.

Funkcje pomijają zakres klas podczas wyszukiwania nazw

Klasy mają zasięg lokalny podczas definicji, ale funkcje wewnątrz klasy nie używają tego zasięgu podczas wyszukiwania nazw. Ponieważ lambdy są funkcjami, a wyrażenia są implementowane przy użyciu zakresu funkcji, może to prowadzić do zaskakujących zachowań.

a = 'global'

class Fred:
    a = 'class'  # class scope
    b = (a for i in range(10))  # function scope
    c = [a for i in range(10)]  # function scope
    d = a  # class scope
    e = lambda: a  # function scope
    f = lambda a=a: a  # default argument uses class scope
    
    @staticmethod  # or @classmethod, or regular instance method
    def g():  # function scope
        return a

print(Fred.a)  # class
print(next(Fred.b))  # global
print(Fred.c[0])  # class in Python 2, global in Python 3
print(Fred.d)  # class
print(Fred.e())  # global
print(Fred.f())  # class
print(Fred.g()) # global

Użytkownicy niezaznajomieni z działaniem tego zakresu mogą spodziewać się, że b , c i e wydrukują class .


Od PEP 227 :

Nazwy w zakresie klas nie są dostępne. Nazwy są rozwiązywane w najbardziej wewnętrznym obejmującym zakresie funkcji. Jeśli definicja klasy występuje w łańcuchu zasięgów zagnieżdżonych, proces rozwiązywania pomija definicje klas.

Z dokumentacji Pythona na temat nazewnictwa i wiązania :

Zakres nazw zdefiniowanych w bloku klasy jest ograniczony do bloku klasy; nie obejmuje bloków metod - obejmuje to wyrażenia i wyrażenia generatora, ponieważ są one implementowane przy użyciu zakresu funkcji. Oznacza to, że następujące działania nie powiodą się:

class A:
    a = 42
    b = list(a + i for i in range(10))

W tym przykładzie wykorzystano odniesienia do tej odpowiedzi autorstwa Martijna Pietersa, który zawiera bardziej dogłębną analizę tego zachowania.

Polecenie del

To polecenie ma kilka powiązanych, ale odrębnych form.

del v

Jeśli v jest zmienną, polecenie del v usuwa zmienną ze swojego zakresu. Na przykład:

x = 5
print(x) # out: 5
del x
print(x) # NameError: name 'f' is not defined

Zauważ, że del jest zjawiskiem wiążącym , co oznacza, że o ile wyraźnie nie zaznaczono inaczej (użycie nonlocal lub global ), del v spowoduje, że v będzie lokalny dla bieżącego zakresu. Jeśli zamierzasz usunąć v w zakresie zewnętrznym, użyj nonlocal v lub global v w tym samym zakresie instrukcji del v .

We wszystkich poniższych przypadkach zamiar polecenia jest zachowaniem domyślnym, ale nie jest wymuszony przez język. Klasa może być napisana w sposób, który unieważnia ten zamiar.

del v.name

To polecenie wyzwala połączenie z v.__delattr__(name) .

Chodzi o to, aby name atrybutu była niedostępna. Na przykład:

class A:
    pass

a = A()
a.x = 7
print(a.x) # out: 7
del a.x
print(a.x) # error: AttributeError: 'A' object has no attribute 'x'

del v[item]

To polecenie wyzwala wywołanie do v.__delitem__(item) .

Intencją jest, aby item nie należał do odwzorowania zaimplementowanego przez obiekt v . Na przykład:

x = {'a': 1, 'b': 2}
del x['a']
print(x) #  out: {'b': 2}
print(x['a']) # error: KeyError: 'a'

del v[a:b]

To faktycznie wywołuje v.__delslice__(a, b) .

Intencja jest podobna do opisanej powyżej, ale z plasterkami - zakresami przedmiotów zamiast jednego przedmiotu. Na przykład:

x = [0, 1, 2, 3, 4]
del x[1:3]
print(x) #  out: [0, 3, 4]

Zobacz także Garbage Collection # Polecenie del .

Zakres lokalny a globalny

Jaki jest zasięg lokalny i globalny?

Wszystkie zmienne Pythona, które są dostępne w pewnym momencie kodu, mają zasięg lokalny lub globalny .

Wyjaśnienie jest takie, że zasięg lokalny obejmuje wszystkie zmienne zdefiniowane w bieżącej funkcji, a zasięg globalny obejmuje zmienne zdefiniowane poza bieżącą funkcją.

foo = 1  # global

def func():
    bar = 2  # local
    print(foo)  # prints variable foo from global scope
    print(bar)  # prints variable bar from local scope

Można sprawdzić, które zmienne są w jakim zakresie. Wbudowane funkcje locals() i globals() zwracają całe zakresy jako słowniki.

foo = 1

def func():
    bar = 2
    print(globals().keys())  # prints all variable names in global scope
    print(locals().keys())  # prints all variable names in local scope

Co dzieje się z konfliktami nazw?

foo = 1

def func():
    foo = 2  # creates a new variable foo in local scope, global foo is not affected

    print(foo)  # prints 2

    # global variable foo still exists, unchanged:
    print(globals()['foo'])  # prints 1
    print(locals()['foo'])  # prints 2

Aby zmodyfikować zmienną globalną, użyj słowa kluczowego global :

foo = 1

def func():
    global foo
    foo = 2  # this modifies the global foo, rather than creating a local variable

Zakres jest zdefiniowany dla całego ciała funkcji!

Oznacza to, że zmienna nigdy nie będzie globalna przez połowę funkcji, a później lokalnie, lub odwrotnie.

foo = 1

def func():
    # This function has a local variable foo, because it is defined down below.
    # So, foo is local from this point. Global foo is hidden.

    print(foo) # raises UnboundLocalError, because local foo is not yet initialized
    foo = 7
    print(foo)

Podobnie przeciwieństwo:

foo = 1

def func():
    # In this function, foo is a global variable from the begining

    foo = 7  # global foo is modified

    print(foo)  # 7
    print(globals()['foo'])  # 7

    global foo  # this could be anywhere within the function
    print(foo)  # 7

Funkcje w ramach funkcji

Może istnieć wiele poziomów funkcji zagnieżdżonych w obrębie funkcji, ale w obrębie każdej funkcji istnieje tylko jeden zasięg lokalny dla tej funkcji i zakres globalny. Brak pośrednich zakresów.

foo = 1

def f1():
    bar = 1

    def f2():
        baz = 2
        # here, foo is a global variable, baz is a local variable
        # bar is not in either scope
        print(locals().keys())  # ['baz']
        print('bar' in locals())  # False
        print('bar' in globals())  # False

    def f3():
        baz = 3
        print(bar)  # bar from f1 is referenced so it enters local scope of f3 (closure)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

    def f4():
        bar = 4  # a new local bar which hides bar from local scope of f1
        baz = 4
        print(bar)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

global vs nonlocal (tylko Python 3)

Oba te słowa kluczowe są używane do uzyskania dostępu do zapisu do zmiennych, które nie są lokalne dla bieżących funkcji.

global słowo kluczowe deklaruje, że nazwę należy traktować jako zmienną globalną.

foo = 0  # global foo

def f1():
    foo = 1  # a new foo local in f1
    
    def f2():
        foo = 2  # a new foo local in f2
        
        def f3():
            foo = 3  # a new foo local in f3
            print(foo)  # 3
            foo = 30  # modifies local foo in f3 only
        
        def f4():
            global foo
            print(foo)  # 0
            foo = 100  # modifies global foo

Z drugiej strony, nonlocal (patrz Zmienne nonlocal ), dostępne w Pythonie 3, przejmuje zmienną lokalną z zakresu obejmującego do zakresu lokalnego bieżącej funkcji.

Z dokumentacji Pythona na temat nonlocal :

Instrukcja nielokalna powoduje, że wymienione identyfikatory odnoszą się do poprzednio powiązanych zmiennych w najbliższym obejmującym zakresie z wyłączeniem globali.

Python 3.x 3.0
def f1():
    
    def f2():
        foo = 2  # a new foo local in f2

        def f3():
            nonlocal foo  # foo from f2, which is the nearest enclosing scope
            print(foo)  # 2
            foo = 20  # modifies foo from f2!


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow