Sök…


Syntax

  • global a, b, c
  • icke-lokal a, b
  • x = något # binder x
  • (x, y) = något # binder x och y
  • x + = något # binder x. På samma sätt för alla andra "op ="
  • del x # binder x
  • för x i något: # binder x
  • med något som x: # binder x
  • utom undantag som ex: # binder ex inuti block

Globala variabler

I Python betraktas variabler inuti funktioner som lokala om och bara om de visas i vänster sida av en tilldelningsuppgift eller någon annan bindande händelse; annars slås en sådan bindning upp i slutna funktioner, upp till den globala räckvidden. Detta gäller även om uppdragsbeskrivningen aldrig körs.

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

Normalt kommer en tilldelning inom en omfattning att skugga alla yttre variabler med samma namn:

x = 'Hi'

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

Att förklara ett namn global innebär att, för resten av räckvidden, alla tilldelningar till namnet kommer att ske på modulens toppnivå:

x = 'Hi'

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

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

Det global nyckelordet innebär att uppdrag kommer att ske på modulens toppnivå, inte på programmets toppnivå. Andra moduler behöver fortfarande den vanliga prickade åtkomsten till variabler i modulen.

För att sammanfatta: för att veta om en variabel x är lokal för en funktion bör du läsa hela funktionen:

  1. om du har hittat global x är x en global variabel
  2. Om du har hittat nonlocal x tillhör x en tillslutande funktion och är varken lokal eller global
  3. Om du har hittat x = 5 eller for x in range(3) eller någon annan bindning, är x en lokal variabel
  4. Annars tillhör x något avslutande omfång (funktionsomfång, globalt omfång eller inbyggt)

Lokala variabler

Om ett namn är bundet i en funktion är det som standard endast tillgängligt inom funktionen:

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

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

Kontrollflödeskonstruktioner har ingen inverkan på omfattningen (med undantag för except ), men åtkomst till variabel som ännu inte tilldelats är ett fel:

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

Vanliga bindande operationer är uppdrag, for slingor, och förstärkta uppdrag som a += 5

Icke-lokala variabler

Python 3.x 3.0

Python 3 lade till ett nytt nyckelord som heter nonlocal . Det icke-lokala nyckelordet lägger till ett åsidosättningsområde för det inre omfånget. Du kan läsa allt om det i PEP 3104 . Detta illustreras bäst med ett par kodexempel. Ett av de vanligaste exemplen är att skapa funktion som kan öka:

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

Om du försöker köra den här koden får du en UnboundLocalError eftersom num- variabeln refereras innan den tilldelas i den innersta funktionen. Låt oss lägga nonlocal till mixen:

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

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

I princip kan nonlocal tilldela variabler i ett yttre omfång, men inte till ett globalt omfång. Så du kan inte använda nonlocal i vår counter eftersom den skulle försöka tilldela till ett globalt omfång. Prova, så får du snabbt en SyntaxError . Istället måste du använda nonlocal i en kapslad funktion.

(Observera att funktionaliteten som presenteras här är bättre implementerad med generatorer.)

Bindande förekomst

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

Var och en av ovanstående uttalanden är en bindande händelse - x blir bundet till det objekt som betecknas med 5 . Om detta uttalande visas i en funktion, är x som standard lokalfunktion. Se avsnittet "Syntax" för en lista med bindande uttalanden.

Funktioner hoppar över klassomfånget när du letar upp namn

Klasser har ett lokalt omfång under definitionen, men funktioner i klassen använder inte det omfånget när man letar upp namn. Eftersom lambdas är funktioner, och förståelser implementeras med funktionsomfång, kan detta leda till viss överraskande beteende.

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

Användare som inte känner till hur denna omfattning fungerar kan förvänta sig att b , c och e ska skriva ut class .


Från PEP 227 :

Namn i klassens omfattning är inte tillgängliga. Namnen löses i den innersta inneslutna funktionsomfånget. Om en klassdefinition förekommer i en kedja med kapslade områden hoppar upplösningsprocessen över klassdefinitioner.

Från Pythons dokumentation om namngivning och bindande :

Räckvidden för namn definierade i ett klassblock är begränsat till klassblocket; det sträcker sig inte till kodblocken för metoder - detta inkluderar förståelser och generatoruttryck eftersom de implementeras med ett funktionsomfång. Detta betyder att följande kommer att misslyckas:

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

Detta exempel använder referenser från detta svar av Martijn Pieters, som innehåller mer djupgående analys av detta beteende.

Del-kommandot

Detta kommando har flera relaterade men tydliga former.

del v

Om v är en variabel tar kommandot del v bort variabeln från dess omfattning. Till exempel:

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

Observera att del är en bindande förekomst , vilket innebär att om inte uttryckligen anges annat (med användning av nonlocal eller global ), del v kommer att göra v lokalt för det aktuella omfånget. Om du tänker ta bort v i ett yttre omfång, använd nonlocal v eller global v i samma räckvidd för del v uttalandet.

I allt följande är avsikten med ett kommando ett standardbeteende men verkställs inte av språket. En klass kan skrivas på ett sätt som upphäver denna avsikt.

del v.name

Detta kommando utlöser ett samtal till v.__delattr__(name) .

Avsikten är att göra attributets name inte tillgängligt. Till exempel:

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]

Detta kommando utlöser ett samtal till v.__delitem__(item) .

Avsikten är att item kommer att höra i den kartläggning som implementeras av objektet v . Till exempel:

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

del v[a:b]

Detta kallar faktiskt v.__delslice__(a, b) .

Avsikten liknar den som beskrivs ovan, men med skivor - objektintervall istället för en enda artikel. Till exempel:

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

Se även Garbage Collection # Del-kommandot .

Local vs Global Scope

Vad är lokalt och globalt?

Alla Python-variabler som är tillgängliga vid någon punkt i kod är antingen i lokal omfattning eller i global omfattning .

Förklaringen är att det lokala omfånget inkluderar alla variabler som definieras i den aktuella funktionen och att det globala omfånget inkluderar variabler definierade utanför den aktuella funktionen.

foo = 1  # global

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

Man kan undersöka vilka variabler som finns i vilken omfattning. Inbyggda funktioner locals() och globals() returnerar hela räckvidden som ordböcker.

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

Vad händer med namnkollisioner?

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

Om du vill ändra en global variabel använder du sökordet global :

foo = 1

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

Räckvidden definieras för hela funktionen!

Vad det betyder är att en variabel aldrig kommer att vara global för en hälft av funktionen och lokal efteråt, eller tvärtom.

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)

Likaså det motsatta:

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

Funktioner inom funktioner

Det kan finnas många nivåer av funktioner som är kapslade i funktioner, men inom vilken som helst funktion finns det bara ett lokalt omfång för den funktionen och det globala omfånget. Det finns inga mellanområden.

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

Båda dessa nyckelord används för att få skrivåtkomst till variabler som inte är lokala för de aktuella funktionerna.

Det global nyckelordet förklarar att ett namn ska behandlas som en global variabel.

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

Å andra sidan tar nonlocal (se nonlocal lokala variabler ), tillgängliga i Python 3, en lokal variabel från ett slutande omfång till det lokala omfånget för aktuell funktion.

Från Python-dokumentationen om nonlocal :

Det icke-lokala uttalandet får de listade identifierarna att hänvisa till tidigare bundna variabler i närmaste omslutande räckvidd exklusive globaler.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow