Ricerca…


Sintassi

  • globale a, b, c
  • non locale a, b
  • x = qualcosa # lega x
  • (x, y) = qualcosa # lega x e y
  • x + = qualcosa # lega x. Allo stesso modo per tutti gli altri "op ="
  • del x # lega x
  • per x in qualcosa: # si lega x
  • con qualcosa come x: # si lega x
  • tranne Eccezione come ex: # si lega ex al blocco

Variabili globali

In Python, le variabili all'interno delle funzioni sono considerate locali se e solo se compaiono nella parte sinistra di un'istruzione di assegnazione, o qualche altra occorrenza di associazione; in caso contrario tale associazione viene cercata nel racchiudere le funzioni, fino allo scopo globale. Questo è vero anche se l'istruzione di assegnazione non viene mai eseguita.

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

Normalmente, un'assegnazione all'interno di un oscilloscopio ombreggia qualsiasi variabile esterna con lo stesso nome:

x = 'Hi'

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

Dichiarare un nome global significa che, per il resto dello scope, qualsiasi assegnazione al nome avverrà al livello principale del modulo:

x = 'Hi'

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

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

La parola chiave global indica che gli assegnamenti avverranno al livello più alto del modulo, non al livello principale del programma. Altri moduli avranno ancora bisogno del solito accesso puntato alle variabili all'interno del modulo.

Riassumendo: per sapere se una variabile x è locale a una funzione, dovresti leggere l' intera funzione:

  1. se hai trovato global x , x è una variabile globale
  2. Se hai trovato nonlocal x , x appartiene a una funzione di inclusione e non è né locale né globale
  3. Se hai trovato x = 5 o for x in range(3) o qualche altro legame, allora x è una variabile locale
  4. Altrimenti x appartiene ad un ambito che racchiude (scope della funzione, scope globale o builtin)

Variabili locali

Se un nome è associato a una funzione, per impostazione predefinita è accessibile solo all'interno della funzione:

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

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

I costrutti del flusso di controllo non hanno alcun impatto sull'ambito (ad eccezione di except ), ma l'accesso alla variabile che non è stata ancora assegnata è un errore:

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

Operazioni comuni vincolanti assegnazioni, for cicli e assegnazioni aumentata come a += 5

Variabili non locali

Python 3.x 3.0

Python 3 ha aggiunto una nuova parola chiave chiamata nonlocal . La parola chiave nonlocale aggiunge un ambito prioritario all'ambito interno. Puoi leggere tutto su di esso in PEP 3104 . Questo è meglio illustrato con un paio di esempi di codice. Uno degli esempi più comuni è creare una funzione che può incrementare:

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

Se provi a eseguire questo codice, riceverai un UnboundLocalError perché la variabile num viene referenziata prima che venga assegnata nella funzione più interna. Aggiungiamo nonlocal al mix:

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

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

Fondamentalmente nonlocal ti permetterà di assegnare alle variabili in un ambito esterno, ma non un ambito globale. Quindi non è possibile utilizzare non nonlocal nella nostra funzione counter perché in tal caso proverebbe ad assegnarli a un ambito globale. Fare un tentativo e si otterrà rapidamente un SyntaxError . Invece devi usare nonlocal in una funzione annidata.

(Si noti che la funzionalità presentata qui è implementata meglio usando i generatori).

Evento obbligatorio

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

Ciascuna delle affermazioni precedenti è un'occorrenza di associazione - x si lega all'oggetto denotato da 5 . Se questa istruzione appare all'interno di una funzione, x sarà function-local per impostazione predefinita. Vedere la sezione "Sintassi" per un elenco di istruzioni vincolanti.

Le funzioni ignorano l'ambito della classe durante la ricerca dei nomi

Le classi hanno un ambito locale durante la definizione, ma le funzioni all'interno della classe non usano quell'ambito quando cercano i nomi. Poiché lambda sono funzioni e le interpretazioni vengono implementate utilizzando l'ambito della funzione, ciò può portare a comportamenti sorprendenti.

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

Gli utenti che non hanno familiarità con il funzionamento di questo scope potrebbero aspettarsi che b , c ed e stampino la class .


Da PEP 227 :

I nomi nella portata della classe non sono accessibili. I nomi sono risolti nello scope della funzione di chiusura più interna. Se una definizione di classe si verifica in una catena di ambiti nidificati, il processo di risoluzione ignora le definizioni di classe.

Dalla documentazione di Python su denominazione e associazione :

L'ambito dei nomi definiti in un blocco di classe è limitato al blocco di classe; non si estende ai blocchi di codice dei metodi - questo include le comprensioni e le espressioni del generatore poiché sono implementati usando un ambito di funzione. Ciò significa che il seguente non funzionerà:

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

Questo esempio utilizza i riferimenti di questa risposta di Martijn Pieters, che contiene un'analisi più approfondita di questo comportamento.

Il comando

Questo comando ha diverse forme correlate ma distinte.

del v

Se v è una variabile, il comando del v rimuove la variabile dal suo ambito. Per esempio:

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

Si noti che del è un'occorrenza di associazione , il che significa che, a meno che non sia specificato esplicitamente altrimenti (usando nonlocal o global ), del v renderà v local allo scope corrente. Se si intende eliminare v in un ambito esterno, utilizzare nonlocal v global v o global v nello stesso ambito dell'istruzione del v .

In tutto quanto segue, l'intenzione di un comando è un comportamento predefinito, ma non viene applicato dalla lingua. Una classe potrebbe essere scritta in modo tale da invalidare questa intenzione.

del v.name

Questo comando attiva una chiamata a v.__delattr__(name) .

L'intenzione è di rendere il name dell'attributo name disponibile. Per esempio:

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]

Questo comando attiva una chiamata a v.__delitem__(item) .

L'intenzione è che l' item non apparterrà alla mappatura implementata dall'oggetto v . Per esempio:

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

del v[a:b]

Questo in realtà chiama v.__delslice__(a, b) .

L'intenzione è simile a quella descritta sopra, ma con sezioni: intervalli di elementi anziché un singolo elemento. Per esempio:

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

Vedi anche Garbage Collection # Il comando del .

Local vs Global Scope

Quali sono gli obiettivi locali e globali?

Tutte le variabili di Python che sono accessibili ad un certo punto nel codice sono in ambito locale o nell'ambito globale .

La spiegazione è che l'ambito locale include tutte le variabili definite nella funzione corrente e l'ambito globale include variabili definite al di fuori della funzione corrente.

foo = 1  # global

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

Si può ispezionare quali variabili sono in quale ambito. Le funzioni built-in locals() e globals() restituiscono l'intero scope come dizionari.

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

Cosa succede con le scontro sul nome?

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

Per modificare una variabile globale, utilizzare la parola chiave global :

foo = 1

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

L'ambito è definito per l'intero corpo della funzione!

Ciò che significa è che una variabile non sarà mai globale per metà della funzione e locale in seguito, o viceversa.

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)

Allo stesso modo, la oposite:

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

Funzioni all'interno delle funzioni

Possono esserci molti livelli di funzioni annidati all'interno delle funzioni, ma all'interno di una funzione c'è solo un ambito locale per quella funzione e l'ambito globale. Non ci sono ambiti intermedi.

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 (solo Python 3)

Entrambe queste parole chiave sono utilizzate per ottenere l'accesso in scrittura a variabili che non sono locali alle funzioni correnti.

La parola chiave global dichiara che un nome dovrebbe essere trattato come una variabile globale.

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

D'altra parte, nonlocal (vedi Variabili nonlocal ), disponibile in Python 3, prende una variabile locale da un ambito che racchiude l'ambito locale della funzione corrente.

Dalla documentazione Python su nonlocal :

L'istruzione nonlocale fa sì che gli identificatori elencati facciano riferimento a variabili associate in precedenza nello scope che racchiude il più vicino escludendo le 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow