Zoeken…


Syntaxis

  • globaal a, b, c
  • niet-lokaal a, b
  • x = iets # bindt x
  • (x, y) = iets # bindt x en y
  • x + = iets # bindt x. Zo ook voor alle andere "op ="
  • del x # bindt x
  • voor x in iets: # bindt x
  • met iets als x: # bindt x
  • behalve Uitzondering als ex: # bindt ex binnen blok

Globale variabelen

In Python worden variabelen in functies als lokaal beschouwd als en alleen als ze aan de linkerkant van een toewijzingsinstructie verschijnen, of een andere bindende gebeurtenis; anders wordt een dergelijke binding opgezocht in omsluitende functies, tot aan de globale scope. Dit geldt zelfs als de toewijzingsopdracht nooit wordt uitgevoerd.

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

Normaal gesproken zal een toewijzing binnen een scope eventuele externe variabelen met dezelfde naam overschaduwen:

x = 'Hi'

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

Door een naam global verklaren, worden voor de rest van de scope toewijzingen aan de naam op het hoogste niveau van de module uitgevoerd:

x = 'Hi'

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

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

Het global trefwoord betekent dat toewijzingen op het hoogste niveau van de module plaatsvinden, niet op het hoogste niveau van het programma. Andere modules zullen nog steeds de gebruikelijke gestippelde toegang tot variabelen binnen de module nodig hebben.

Samenvattend: om te weten of een variabele x lokaal is voor een functie, moet u de hele functie lezen:

  1. als je global x hebt gevonden, dan is x een globale variabele
  2. Als u nonlocal x hebt gevonden, behoort x tot een omsluitende functie en is noch lokaal noch globaal
  3. Als je x = 5 of for x in range(3) of een andere binding hebt gevonden, dan is x een lokale variabele
  4. Anders behoort x tot een omsluitend bereik (functiebereik, algemeen bereik of ingebouwde)

Lokale variabelen

Als een naam binnen een functie is gebonden , is deze standaard alleen toegankelijk binnen de functie:

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

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

Besturingsstroom constructen hebben geen invloed op de omvang (behalve except ), maar de toegang variabele die nog niet is toegewezen een fout:

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

Veelgebruikte bindbewerkingen zijn toewijzingen, for lussen en uitgebreide toewijzingen zoals a += 5

Niet-lokale variabelen

Python 3.x 3.0

Python 3 heeft een nieuw trefwoord toegevoegd met de naam nonlocal . Het niet-lokale trefwoord voegt een overschrijving aan het binnenbereik toe. Je kunt er alles over lezen in PEP 3104 . Dit wordt het best geïllustreerd met een paar codevoorbeelden. Een van de meest voorkomende voorbeelden is om een functie te maken die kan worden verhoogd:

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

Als u deze code probeert uit te voeren, ontvangt u een UnboundLocalError omdat naar de variabele num wordt verwezen voordat deze in de binnenste functie wordt toegewezen. Laten we niet-lokaal aan de mix toevoegen:

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

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

In principe kunt u nonlocal variabelen in een extern bereik toewijzen, maar geen algemeen bereik. U kunt dus niet- nonlocal niet gebruiken in onze counter omdat het dan zou proberen toe te wijzen aan een globale scope. Probeer het eens en u krijgt snel een SyntaxError . In plaats daarvan moet u nonlocal in een geneste functie.

(Merk op dat de hier gepresenteerde functionaliteit beter is geïmplementeerd met behulp van generatoren.)

Bindend voorkomen

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

Elk van de bovenstaande uitspraken is bindend - x wordt gebonden aan het object aangegeven met 5 . Als deze instructie in een functie wordt weergegeven, is x standaard functie-lokaal. Zie de sectie "Syntaxis" voor een lijst met bindende verklaringen.

Functies slaan klassebereik over bij het opzoeken van namen

Klassen hebben een lokaal bereik tijdens de definitie, maar functies binnen de klasse gebruiken dat bereik niet bij het opzoeken van namen. Omdat lambda's functies zijn en begrippen worden geïmplementeerd met behulp van functiebereik, kan dit tot verrassend gedrag leiden.

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

Gebruikers die niet weten hoe deze scope werkt, kunnen verwachten dat b , c en e class afdrukken.


Van PEP 227 :

Namen in klassebereik zijn niet toegankelijk. Namen worden omgezet in het binnenste omringende functiebereik. Als een klassedefinitie voorkomt in een reeks geneste bereiken, slaat het resolutieproces klassedefinities over.

Uit de documentatie van Python over naamgeving en binding :

Het bereik van namen gedefinieerd in een klasseblok is beperkt tot het klasseblok; het strekt zich niet uit tot de codeblokken van methoden - dit omvat begrip en generatoruitdrukkingen, aangezien deze worden geïmplementeerd met behulp van een functiebereik. Dit betekent dat het volgende mislukt:

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

Dit voorbeeld gebruikt referenties uit dit antwoord van Martijn Pieters, die een meer diepgaande analyse van dit gedrag bevat.

Het del commando

Deze opdracht heeft verschillende gerelateerde maar toch verschillende vormen.

del v

Als v een variabele is, verwijdert de opdracht del v de variabele uit het bereik. Bijvoorbeeld:

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

Merk op dat del een bindende gebeurtenis is , wat betekent dat tenzij del v expliciet anders wordt vermeld (gebruikmakend van nonlocal of global ), del v ervoor zorgt dat v lokaal is voor de huidige scope. Als u v in een externe scope wilt verwijderen, gebruikt u nonlocal v of global v in dezelfde scope als de instructie del v .

In het volgende is de intentie van een opdracht een standaardgedrag, maar wordt niet afgedwongen door de taal. Een klasse kan zo worden geschreven dat deze intentie ongeldig wordt.

del v.name

Deze opdracht v.__delattr__(name) een aanroep naar v.__delattr__(name) .

De bedoeling is om het attribuut te maken name onbeschikbaar. Bijvoorbeeld:

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]

Deze opdracht v.__delitem__(item) een aanroep naar v.__delitem__(item) .

De bedoeling is dat het item niet thuishoort in de afbeelding die door het object v geïmplementeerd. Bijvoorbeeld:

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

del v[a:b]

Dit roept eigenlijk v.__delslice__(a, b) .

De bedoeling is vergelijkbaar met die hierboven beschreven, maar met plakjes - reeksen items in plaats van een enkel item. Bijvoorbeeld:

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

Zie ook Garbage Collection # De opdracht del .

Lokaal versus wereldwijd bereik

Wat is lokaal en wereldwijd bereik?

Alle variabelen van Python die op enig moment in de code toegankelijk zijn, bevinden zich in lokaal bereik of in globaal bereik .

De verklaring is dat het lokale bereik alle variabelen omvat die in de huidige functie zijn gedefinieerd en het globale bereik omvat variabelen die buiten de huidige functie zijn gedefinieerd.

foo = 1  # global

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

Men kan inspecteren welke variabelen zich in welke scope bevinden. Ingebouwde functies locals() en globals() geven de hele scopes terug als woordenboeken.

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

Wat gebeurt er met naamconflicten?

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

Gebruik trefwoord global om een globale variabele te wijzigen:

foo = 1

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

Het bereik is gedefinieerd voor het hele lichaam van de functie!

Wat het betekent is dat een variabele nooit de helft van de functie en daarna lokaal zal zijn, of vice versa.

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)

Evenzo is het tegenovergestelde:

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

Functies binnen functies

Er kunnen veel functieniveaus zijn genest in functies, maar binnen elke functie is er slechts één lokale scope voor die functie en de globale scope. Er zijn geen tussenbereiken.

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

Beide trefwoorden worden gebruikt om schrijftoegang te krijgen tot variabelen die niet lokaal zijn voor de huidige functies.

Het global sleutelwoord verklaart dat een naam als een globale variabele moet worden behandeld.

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

Aan de andere kant neemt nonlocal (zie Niet- lokale variabelen ), beschikbaar in Python 3, een lokale variabele van een omsluitend bereik in het lokale bereik van de huidige functie.

Uit de Python-documentatie op nonlocal :

De niet-lokale instructie zorgt ervoor dat de weergegeven id's verwijzen naar eerder gebonden variabelen in het dichtstbijzijnde omsluitende bereik exclusief globalen.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow