Vraag Globale variabelen in een functie gebruiken


Hoe kan ik een globale variabele in een functie maken of gebruiken?

Als ik een globale variabele in één functie maak, hoe kan ik die globale variabele in een andere functie gebruiken? Moet ik de globale variabele opslaan in een lokale variabele van de functie die toegang nodig heeft?


2466
2018-01-08 05:45


oorsprong


antwoorden:


U kunt een globale variabele in andere functies gebruiken door deze als te declareren global in elke functie die eraan toewijst:

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print(globvar)     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

Ik stel me voor dat de reden ervoor is dat, aangezien globale variabelen zo gevaarlijk zijn, Python ervoor wil zorgen dat je echt weet dat dat is waar je mee speelt door expliciet de global trefwoord.

Zie andere antwoorden als u een globale variabele in verschillende modules wilt delen.


3497
2018-01-08 08:39



Als ik je situatie goed begrijp, is wat je ziet het resultaat van hoe Python omgaat met lokale (functie) en globale (module) naamruimten.

Stel dat je zo'n module hebt:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

Je zou verwachten dat dit 42 zal afdrukken, maar in plaats daarvan 5. drukt. Zoals al is vermeld, als je een 'global'verklaring aan func1(), dan func2() zal 42 afdrukken.

def func1():
    global myGlobal
    myGlobal = 42

Wat hier aan de hand is, is dat Python veronderstelt dat elke naam dat is toegewezen aan, waar dan ook binnen een functie, is lokaal voor die functie tenzij expliciet anders aangegeven. Als het alleen is lezing van een naam, en de naam bestaat niet lokaal, maar zal proberen de naam op te zoeken in om het even welke scopes (bijvoorbeeld de globale scope van de module).

Wanneer u 42 aan de naam toewijst myGlobalDaarom maakt Python een lokale variabele die de globale variabele met dezelfde naam overschaduwt. Dat lokale gaat buiten bereik en is Opgeschoond wanneer func1() komt terug; ondertussen, func2() kan nooit iets anders zien dan de (ongewijzigde) algemene naam. Merk op dat deze naamruimtebeslissing plaatsvindt tijdens het compileren, niet tijdens runtime - als u de waarde van zou lezen myGlobal binnen func1() voordat je het toewijst, zou je een krijgen UnboundLocalError, omdat Python al heeft besloten dat het een lokale variabele moet zijn, maar er is nog geen waarde aan verbonden. Maar door de 'global'statement, zeg tegen Python dat het ergens anders naar de naam moet zoeken in plaats van het lokaal toe te kennen.

(Ik geloof dat dit gedrag grotendeels is ontstaan ​​door een optimalisatie van lokale naamruimten - zonder dit gedrag zou de VM van Python minstens drie naamzoekopdrachten moeten uitvoeren telkens als een nieuwe naam wordt toegewezen aan een functie (om ervoor te zorgen dat de naam niet wist t bestaat al op module / ingebouwd niveau), wat een zeer algemene operatie aanzienlijk zou vertragen.)


660
2018-01-08 09:19



Misschien wilt u de notie van namespaces. In Python, de module is de natuurlijke plaats voor globaal gegevens:

Elke module heeft zijn eigen privé-symbooltabel, die wordt gebruikt als de globale symbooltabel door alle functies die in de module zijn gedefinieerd. De auteur van een module kan dus globale variabelen in de module gebruiken zonder zich zorgen te maken over onbedoelde clashes met de globale variabelen van een gebruiker. Aan de andere kant, als je weet wat je doet, kun je de globale variabelen van een module aanraken met dezelfde notatie die wordt gebruikt om naar zijn functies te verwijzen, modname.itemname.

Een specifiek gebruik van global-in-a-module wordt hier beschreven - how-do-i-share-global-variabelen-across-modules, en voor de volledigheid wordt de inhoud hier gedeeld:

De canonieke manier om informatie over modules binnen een enkel programma te delen, is om een ​​speciale configuratiemodule te maken (vaak configuratie of cfg genoemd). Importeer de configuratiemodule gewoon in alle modules van uw applicatie; de module wordt dan beschikbaar als een globale naam. Omdat er slechts één exemplaar van elke module is, worden alle wijzigingen die in het moduleobject zijn aangebracht, overal weergegeven. Bijvoorbeeld:

Bestand: config.py

x = 0   # Default value of the 'x' configuration setting

Bestand: mod.py

import config
config.x = 1

Bestand: main.py

import config
import mod
print config.x

175
2018-01-08 05:59



Python gebruikt een eenvoudige heuristiek om te bepalen in welk bereik hij een variabele moet laden van, tussen lokaal en globaal. Als de naam van een variabele aan de linkerkant van een toewijzing wordt weergegeven, maar niet globaal wordt verklaard, wordt deze als lokaal beschouwd. Als het niet aan de linkerkant van een opdracht wordt weergegeven, wordt aangenomen dat het globaal is.

>>> import dis
>>> def foo():
...     global bar
...     baz = 5
...     print bar
...     print baz
...     print quux
... 
>>> dis.disassemble(foo.func_code)
  3           0 LOAD_CONST               1 (5)
              3 STORE_FAST               0 (baz)

  4           6 LOAD_GLOBAL              0 (bar)
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  5          11 LOAD_FAST                0 (baz)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       

  6          16 LOAD_GLOBAL              1 (quux)
             19 PRINT_ITEM          
             20 PRINT_NEWLINE       
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        
>>> 

Zie hoe baz, die aan de linkerkant van een opdracht wordt weergegeven in foo(), is de enige LOAD_FAST variabel.


75
2017-07-12 12:35



Als u in een functie naar een globale variabele wilt verwijzen, kunt u de globaal sleutelwoord om te verklaren welke variabelen globaal zijn. U hoeft het niet in alle gevallen te gebruiken (zoals iemand hier ten onrechte beweert) - als de naam waarnaar wordt verwezen in een uitdrukking niet kan worden gevonden in de lokale scope of scopes in de functies waarin deze functie is gedefinieerd, wordt deze opgezocht tussen globale variabelen.

Als u echter een nieuwe variabele toewijst die niet globaal is gedeclareerd in de functie, wordt deze impliciet als lokaal gedeclareerd en kan deze een bestaande algemene variabele met dezelfde naam overschaduwen.

Ook zijn globale variabelen nuttig, in tegenstelling tot sommige OOP-fanatici die anders beweren - vooral voor kleinere scripts, waar OOP te veel van het goede is.


47
2018-01-08 09:03



Naast de reeds bestaande antwoorden en om dit nog verwarrender te maken:

In Python zijn variabelen waarnaar alleen in een functie wordt verwezen, wel    impliciet globaal. Als een variabele een nieuwe waarde krijgt toegewezen, waar dan ook   binnen het lichaam van de functie wordt aangenomen dat dit een a is lokaal. Als een variabele   is ooit een nieuwe waarde toegewezen binnen de functie, de variabele is   impliciet lokaal, en u moet het expliciet als 'globaal' verklaren.

Hoewel een beetje verrassend in het begin, legt een moment van overweging uit   deze. Aan de ene kant vereist het vereisen van globaal voor toegewezen variabelen een   bar tegen onbedoelde bijwerkingen. Aan de andere kant, als global was   vereist voor alle wereldwijde verwijzingen, zou u globaal alle gebruiken   tijd. Je zou elke verwijzing naar een ingebouwde als globaal moeten verklaren   functie of een onderdeel van een geïmporteerde module. Deze rommel zou   het nut van de globale verklaring voor identificatie te verslaan   bijwerkingen.

Bron: Wat zijn de regels voor lokale en globale variabelen in Python?.


36
2017-07-04 10:23



Als ik een globale variabele in één functie maak, hoe kan ik die variabele in een andere functie gebruiken?

We kunnen een globale creëren met de volgende functie:

def create_global_variable():
    global global_variable # must declare it to be a global first
    # modifications are thus reflected on the module's global scope
    global_variable = 'Foo' 

Het schrijven van een functie voert zijn code niet echt uit. Dus we noemen het create_global_variable functie:

>>> create_global_variable()

Globale waarden gebruiken zonder wijziging

Je kunt het gewoon gebruiken, zolang je niet verwacht om te veranderen naar welk object het verwijst:

Bijvoorbeeld,

def use_global_variable():
    return global_variable + '!!!'

en nu kunnen we de globale variabele gebruiken:

>>> use_global_variable()
'Foo!!!'

Wijziging van de globale variabele vanuit een functie

Als u de globale variabele op een ander object wilt richten, moet u het algemene sleutelwoord opnieuw gebruiken:

def change_global_variable():
    global global_variable
    global_variable = 'Bar'

Merk op dat na het schrijven van deze functie, de code die deze feitelijk wijzigt nog steeds niet is uitgevoerd:

>>> use_global_variable()
'Foo!!!'

Dus na het aanroepen van de functie:

>>> change_global_variable()

we kunnen zien dat de globale variabele is veranderd. De global_variable naam verwijst nu naar 'Bar':

>>> use_global_variable()
'Bar!!!'

Merk op dat "global" in Python niet echt globaal is - het is alleen globaal voor het moduleniveau. Dus het is alleen beschikbaar voor functies geschreven in de modules waarin het globaal is. Functies onthouden de module waarin ze zijn geschreven, dus wanneer ze worden geëxporteerd naar andere modules, kijken ze nog steeds in de module waarin ze zijn gemaakt om globale variabelen te vinden.

Lokale variabelen met dezelfde naam

Als u een lokale variabele met dezelfde naam maakt, wordt een algemene variabele overschaduwd:

def use_local_with_same_name_as_global():
    # bad name for a local variable, though.
    global_variable = 'Baz' 
    return global_variable + '!!!'

>>> use_local_with_same_name_as_global()
'Baz!!!'

Maar het gebruik van die verkeerd benoemde lokale variabele verandert de globale variabele niet:

>>> use_global_variable()
'Bar!!!'

Houd er rekening mee dat u de lokale variabelen met dezelfde namen als globals niet moet gebruiken, tenzij u precies weet wat u doet en daarvoor een zeer goede reden hebt. Ik ben nog niet zo'n reden tegengekomen.


31
2018-01-01 19:55



Met parallelle uitvoering kunnen globale variabelen onverwachte resultaten veroorzaken als u niet begrijpt wat er gebeurt. Hier is een voorbeeld van het gebruik van een globale variabele binnen multiprocessing. We kunnen duidelijk zien dat elk proces werkt met een eigen kopie van de variabele:

import multiprocessing
import os
import random
import sys
import time

def worker(new_value):
    old_value = get_value()
    set_value(random.randint(1, 99))
    print('pid=[{pid}] '
          'old_value=[{old_value:2}] '
          'new_value=[{new_value:2}] '
          'get_value=[{get_value:2}]'.format(
          pid=str(os.getpid()),
          old_value=old_value,
          new_value=new_value,
          get_value=get_value()))

def get_value():
    global global_variable
    return global_variable

def set_value(new_value):
    global global_variable
    global_variable = new_value

global_variable = -1

print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after  set_value(), get_value() = [%s]' % get_value())

processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))

Output:

before set_value(), get_value() = [-1]
after  set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]

28
2017-10-03 05:41



U moet verwijzen naar de globale variabele in elke functie die u wilt gebruiken.

Als volgt:

var = "test"

def printGlobalText():
    global var #wWe are telling to explicitly use the global version
    var = "global from printGlobalText fun."
    print "var from printGlobalText: " + var

def printLocalText():
    #We are NOT telling to explicitly use the global version, so we are creating a local variable
    var = "local version from printLocalText fun"
    print "var from printLocalText: " + var

printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""

19
2017-12-20 12:45