Python Language
Variabelt omfattning och bindning
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:
- om du har hittat
global x
ärx
en global variabel - Om du har hittat
nonlocal x
tillhörx
en tillslutande funktion och är varken lokal eller global - Om du har hittat
x = 5
ellerfor x in range(3)
eller någon annan bindning, ärx
en lokal variabel - 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 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 avnonlocal
ellerglobal
),del v
kommer att görav
lokalt för det aktuella omfånget. Om du tänker ta bortv
i ett yttre omfång, användnonlocal v
ellerglobal v
i samma räckvidd fördel 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.
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!