Hoe definieer je een vrije variabele in python?

De local/global/free variabeledefinities van python doc:

Als een naam in een blok is gebonden, is het een lokale variabelevan dat blok, tenzij gedeclareerd als niet-lokaal. Als een naam op moduleniveau gebonden is, is het een algemene variabele. (De variabelen van het modulecodeblok zijn lokaal en globaal.) Als een variabele in een codeblok wordt gebruikt maar daar niet is gedefinieerd, is het een vrije variabele.


Code 1:

>>> x = 0
>>> def foo():
...   print(x)
...   print(locals())
... 
>>> foo()
0
{}

Code 2:

>>> def bar():
...   x = 1
...   def foo():
...     print(x)
...     print(locals())
...   foo()
... 
>>> bar()
1
{'x':1}

Vrije variabelenworden geretourneerd door locals()wanneer het wordt aangeroepen in functieblokken, maar niet in klassenblokken.


In Code 1is xeen algemene variabeleen wordt deze gebruikt, maar niet gedefinieerd in foo().
Het is echter geen vrije variabele, omdat deze niet wordt geretourneerd door locals().
Ik denk dat het niet is wat de dokter zei. Is er een technische definitie voor vrije variabele?


Antwoord 1, autoriteit 100%

Definitie van een vrije variabele: gebruikt, maar noch globaal noch gebonden.

Bijvoorbeeld:

  1. xis niet gratis in Code 1, omdat het een algemenevariabele is.
  2. xis niet vrij in bar()in Code 2, omdat het een gebondenvariabele is.
  3. xis gratis in foo().

Python maakt dit onderscheid vanwege sluitingen. Een vrije variabele is niet gedefinieerd in de huidige omgeving, d.w.z. e. verzameling van lokale variabelen, en is ook geeneen globale variabele! Daarom moet het ergens anders worden gedefinieerd. En dit is het concept van sluitingen. In Code 2 sluit foo()op xgedefinieerd in bar(). Python gebruikt lexicale scope. Dit betekent dat de tolk de reikwijdte kan bepalen door alleen maar naar de code te kijken.

Bijvoorbeeld: xstaat bekend als een variabele in foo(), omdat foo()wordt omsloten door bar()en xis gebonden in bar().

Globaal bereik wordt speciaal behandeld door Python. Het zou mogelijk zijn om het globale bereik als een buitenste bereik te zien, maar dit wordt niet gedaan vanwege de prestaties (denk ik). Daarom is het niet mogelijk dat xzowel gratisals algemeenis.

Vrijstelling

Het leven is niet zo eenvoudig. Er bestaan ​​gratis globalevariabelen. Python-documenten (uitvoeringsmodel) zegt:

De globale instructie heeft hetzelfde bereik als een naambindingsbewerking in hetzelfde blok. Als het dichtstbijzijnde omsluitende bereik voor een vrije variabele een globale instructie bevat, wordt de vrije variabele behandeld als een globale.

>>> x = 42
>>> def foo():
...   global x
...   def baz():
...     print(x)
...     print(locals())
...   baz()
... 
>>> foo()
42
{}

Dat wist ik zelf niet. We zijn hier allemaal om te leren.


Antwoord 2, autoriteit 14%

Voor zover ik heb begrepen is de documentatie inderdaad een beetje dubbelzinnig over vrije variabelen. Er zijn vrije globale variabelendie worden behandeld als gewone globalen en lexicaal gebonden vrije variabelen. Eli Bendersky vat het mooi samen in een blogpost op symbooltabellen:

Helaas is er een steno in de kern van Python die lezers in eerste instantie in verwarring kan brengen over wat precies een “vrije” variabele is. Gelukkig is het een heel kleine verwarring die gemakkelijk te ordenen is. De referentie van het uitvoeringsmodel zegt:

Als een variabele wordt gebruikt in een codeblok maar daar niet is gedefinieerd, is het een vrije variabele.

Dit komt overeen met de formele definitie. In de bron wordt “free” echter gebruikt als een afkorting voor “lexicaal gebonden vrije variabele”(dwz variabelen waarvoor een binding is gevonden in een omsluitende scope), waarbij “globaal” is gebruikt om te verwijzen naar alle resterende vrije variabelen. Dus bij het lezen van de CPython-broncode is het belangrijk om te onthouden dat de volledige set gratis variabelen zowel de variabelen bevat die specifiek als “gratis” zijn getagd, als die welke als “algemeen” zijn getagd.

Om verwarring te voorkomen, zeg ik dus “lexicaal gebonden” als ik wil verwijzen naar de variabelen die in CPython feitelijk als vrij worden behandeld.

(nadruk van mij)

De reden waarom deze steno werd gebruikt, is waarschijnlijk omdat wanneer je een algemene vrije variabelehebt, er geen enkele verandering is in de uitgezonden bytecode. Als een globalvariabele ‘vrij’ is of als dat niet zo is, verandert het feit niet dat de zoekopdracht voor die naam in beide gevallen LOAD_GLOBALzal gebruiken. Dus globale vrije variabelen zijn niet zo speciaal.

Aan de andere kant worden lexicaal gebonden variabelen speciaal behandeld en zijn ze ingesloten in cellobjecten, de objecten zijn de opslagruimte voor lexicaal gebonden vrije variabelenen bevinden zich in het __closure__attribuut voor een bepaalde functie . Een speciale LOAD_DEREF-instructie gemaakt die de aanwezige cellen onderzoekt op de vrije variabelen. De beschrijving voor de LOAD_DEREFinstructie is:

LOAD_DEREF(i)

Laadt de cel in slot i van de cel en vrije variabele opslag

Dus in Python maken vrije variabelen alleen een verschil als concept in situaties waarin een definitie voor een object met status lexicaal (d.w.z. statisch) is genest in een andere definitie voor een object met status.


Antwoord 3, autoriteit 6%

Om beginners niet te laten misleiden, de opmerking hierboven van Nikhil die begint met “Variabelen zijn niets anders dan gereserveerde geheugenlocaties om waarden op te slaan.” is helemaal verkeerd voor Python.

In Python zijn er “namen” en er zijn “waarden”. Waarden hebben typen, geen namen. Geheugenruimte is gereserveerd voor waarden, niet voor namen. We kunnen bijvoorbeeld x = 1 later in de code laten volgen door x = “a string” later gevolgd door x = [3, 9.1]. In de loop van deze toewijzingen wijst de naam x eerst naar een geheel getal, dan naar een string en tenslotte naar een lijst. Wanneer een opdracht klaar is, wordt de naam aan de linkerkant van de opdracht gemaakt om te verwijzen naar de waarde aan de rechterkant van de opdracht. Waarden kunnen onveranderlijk (onveranderlijk) of veranderlijk (veranderlijk) zijn. Gehele getallen, strings, tupels, enz. zijn onveranderlijk; lijsten, enz. zijn veranderlijk. Aangezien gehele getallen onveranderlijk zijn, wanneer er twee uitspraken zijn zoals deze:

x = 4

x = x +1

het tweede statement laat x wijzen naar een nieuwe waarde 5, het verandert niet de waarde in de geheugenlocatie waarnaar x wordt verwezen van 4 naar 5!

Dit is een heel ander model dan bijvoorbeeld de C-taal!


Antwoord 4, autoriteit 4%

Er is geen expliciet sleutelwoord om een ​​vrije variabele in Python te declareren. Op basis van de definitie van een functie en de instructies erin en eromheen, classificeert Python variabelen in gebonden, cel en vrije variabelen.

Het volgende voorbeeld illustreert dit concept met behulp van het code-object van de functie dat de variabelen bevat die in de vorige paragraaf zijn genoemd.

def func(arg1, arg2=2):
    def inner_func(arg3=arg2):
        return arg1, arg3
    arg1, arg2 = None
    return inner_func

Voor ‘func‘:

arg1en arg2zijn gebonden variabelen

arg1is een celvariabeleaangezien het een vrije variabeleis binnen ‘inner_func

• Er zijn geen vrije variabelen.

func.__code__.co_varnames

(‘arg1’, ‘arg2’, ‘inner_func’)

func.__code__.co_cellvars

(‘arg1’,)

func.__code__.co_freevars

()

Voor ‘inner_func‘:

arg3is een gebonden variabele

arg1is een vrije variabele

• Er zijn geen celvariabelen

inner_func.__code__.co_varnames

(‘arg3’,)

inner_func.__code__.co_freevars

(‘arg1’)

inner_func.__code__.co_cellvars

()


Antwoord 5

Variabelen zijn niets anders dan gereserveerde geheugenlocaties om waarden op te slaan. Dit betekent dat wanneer je een variabele aanmaakt, je wat ruimte in het geheugen reserveert.

Op basis van het gegevenstype van een variabele wijst de interpreter geheugen toe en beslist wat er in het gereserveerde geheugen kan worden opgeslagen. Door verschillende gegevenstypen aan variabelen toe te wijzen, kunt u daarom gehele getallen, decimalen of tekens in deze variabelen opslaan.

Waarden toewijzen aan variabelen

Python-variabelen hebben geen expliciete verklaring nodig om geheugenruimte te reserveren. De declaratie gebeurt automatisch wanneer u een waarde aan een variabele toekent. Het gelijkteken (=) wordt gebruikt om waarden aan variabelen toe te kennen.

Other episodes