Globale variabelen gebruiken in een functie

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 dan in een andere functie gebruiken? Moet ik de globale variabele opslaan in een lokale variabele van de functie die toegang nodig heeft?


Antwoord 1, autoriteit 100%

U kunt een globale variabele gebruiken binnen andere functies door deze te declareren als globalbinnen elke functie die er een waarde aan toekent:

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 kan me voorstellen dat de reden hiervoor is dat, aangezien globale variabelen zo gevaarlijk zijn, Python er zeker van wil zijn dat je echt weet waarmee je speelt door expliciet het globalsleutelwoord te vereisen.

Bekijk andere antwoorden als u een globale variabele tussen modules wilt delen.


Antwoord 2, autoriteit 18%

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 een module als deze hebt:

# sample.py
myGlobal = 5
def func1():
    myGlobal = 42
def func2():
    print myGlobal
func1()
func2()

Je zou verwachten dat dit 42 zou afdrukken, maar in plaats daarvan drukt het er 5 af. Zoals al is vermeld, als je een ‘global‘-declaratie toevoegt aan func1(), dan zal func2()42 afdrukken.

def func1():
    global myGlobal
    myGlobal = 42

Wat hier aan de hand is, is dat Python aanneemt dat elke naam die wordt toegewezen aan, waar dan ook binnen een functie, lokaal is voor die functie, tenzij expliciet anders vermeld. Als het alleen leestvan een naam, en de naam bestaat niet lokaal, zal het proberen de naam op te zoeken in elk bevattend bereik (bijv. het globale bereik van de module).

Als je 42 toewijst aan de naam myGlobal, maakt Python daarom een lokale variabele die de globale variabele met dezelfde naam overschaduwt. Die local valt buiten het bereik en wordt garbage-collectedwanneer func1()retourneert; ondertussen kan func2()nooit iets anders zien dan de (onaangepaste) globale naam. Merk op dat deze naamruimtebeslissing plaatsvindt tijdens het compileren, niet tijdens runtime — als u de waarde van myGlobalin func1()zou lezen voordat u eraan toewijst, d krijg een UnboundLocalError, omdat Python al heeft besloten dat het een lokale variabele moet zijn, maar er nog geen waarde aan is gekoppeld. Maar door het ‘global‘ statement te gebruiken, vertel je Python dat het ergens anders naar de naam moet zoeken in plaats van het lokaal toe te wijzen.

(Ik geloof dat dit gedrag grotendeels is ontstaan door een optimalisatie van lokale naamruimten — zonder dit gedrag zou de VM van Python ten minste drie naamzoekacties moeten uitvoeren telkens wanneer een nieuwe naam wordt toegewezen aan een functie (om ervoor te zorgen dat de naam bestond nog niet op module/ingebouwd niveau), wat een veelvoorkomende bewerking aanzienlijk zou vertragen.)


Antwoord 3, autoriteit 5%

Mogelijk wilt u het begrip van Namespaces . In Python, de module is de natuurlijke plaats voor Global gegevens :

Elke module heeft zijn eigen privésymbooltabel, die wordt gebruikt als de wereldwijde symbooltabel door alle functies die in de module zijn gedefinieerd. Zo kan de auteur van een module globale variabelen in de module gebruiken zonder zich zorgen te maken over accidentele botsingen met de wereldwijde variabelen van een gebruiker. Aan de andere kant, als u weet wat u doet, kunt u de globale variabelen van een module aanraken met dezelfde notatie die wordt gebruikt om te verwijzen naar zijn functies, modname.itemname.

Een specifiek gebruik van globale-in-A-module wordt hier beschreven – Hoe deel ik wereldwijde variabelen over modules? , en voor volledigheid wordt de inhoud hier gedeeld:

De canonieke manier om informatie over modules binnen één programma te delen, is het maken van een speciale configuratiemodule (vaak configuratie of CFG ). Importeer gewoon de configuratiemodule in alle modules van uw aanvraag; De module wordt dan beschikbaar als een wereldwijde naam. Omdat er slechts één exemplaar van elke module is, worden alle wijzigingen die worden aangebracht in het Module-object overal weerspiegeld. 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

Antwoord 4, autoriteit 2%

Python gebruikt een eenvoudige heuristiek om te beslissen vanuit welk bereik een variabele moet worden geladen, tussen lokaal en globaal. Als een variabelenaam aan de linkerkant van een toewijzing verschijnt, maar niet globaal is gedeclareerd, wordt aangenomen dat deze lokaal is. Als het niet aan de linkerkant van een opdracht voorkomt, 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        
>>> 

Bekijk hoe baz, dat aan de linkerkant van een opdracht in foo()verschijnt, de enige LOAD_FASTvariabele is.


Antwoord 5

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

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

Bovendien zijn globale variabelen nuttig, in tegenstelling tot sommige OOP-fanaten die anders beweren – vooral voor kleinere scripts, waar OOP overdreven is.


Antwoord 6

Als ik een globale variabele in de ene functie maak, hoe kan ik die variabele dan in een andere functie gebruiken?

We kunnen een globaal maken 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 de functie create_global_variable:

>>> create_global_variable()

Globalen gebruiken zonder aanpassingen

Je kunt het gewoon gebruiken, zolang je niet verwacht 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 naar een ander object wilt verwijzen, moet u het algemene trefwoord 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 daadwerkelijk heeft gewijzigd 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 gewijzigd. De naam global_variablewijst nu naar 'Bar':

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

Merk op dat “algemeen” in Python niet echt globaal is – het is alleen globaal op moduleniveau. Het is dus alleen beschikbaar voor functies die zijn geschreven in de modules waarin het globaal is. Functies onthouden de module waarin ze zijn geschreven, dus wanneer ze naar andere modules worden geëxporteerd, 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, overschaduwt deze een globale variabele:

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 niets aan de globale variabele:

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

Houd er rekening mee dat u de lokale variabelen met dezelfde namen als globals moet vermijden, tenzij u precies weet wat u doet en een zeer goede reden hebt om dit te doen. Ik ben zo’n reden nog niet tegengekomen.

We krijgen hetzelfde gedrag in lessen

Een vervolgreactie vraagt:

wat te doen als ik een globale variabele binnen een functie binnen een klasse wil maken en die variabele binnen een andere functie binnen een andere klasse wil gebruiken?

Hier laat ik zien dat we hetzelfde gedrag krijgen in methoden als in reguliere functies:

class Foo:
    def foo(self):
        global global_variable
        global_variable = 'Foo'
class Bar:
    def bar(self):
        return global_variable + '!!!'
Foo().foo()

En nu:

>>> Bar().bar()
'Foo!!!'

Maar ik zou willen voorstellen om in plaats van globale variabelen te gebruiken klasseattributen, om te voorkomen dat de modulenaamruimte onoverzichtelijk wordt. Merk ook op dat we hier geen self-argumenten gebruiken – dit kunnen klassenmethoden zijn (handig als het class-attribuut van het gebruikelijke cls-argument wordt gemuteerd) of statische methoden (geen selfof cls).


Antwoord 7

In aanvulling op reeds bestaande antwoorden en om het nog verwarrender te maken:

In Python zijn variabelen waarnaar alleen binnen een functie wordt verwezen:
Impliciet Global . Als een variabele overal een nieuwe waarde heeft toegewezen
Binnen het lichaam van de functie wordt verondersteld een lokaal te zijn. Als een variabele
heeft ooit een nieuwe waarde binnen de functie toegewezen, de variabele is
Impliciet lokaal, en je moet het expliciet verklaren als ‘globaal’.

Hoewel een beetje verrassend in het begin, legt het overweging van een moment uit
dit. Aan de ene kant biedt wereldwijd voor toegewezen variabelen een
bar tegen onbedoelde bijwerkingen. Aan de andere kant, als globaal was
Vereist voor alle wereldwijde referenties, zou u wereldwijd alle
tijd. Je zou moeten verklaren als wereldwijde verwijzing naar een ingebouwde
functie of naar een component van een geïmporteerde module. Deze rommel zou
versla het bruikbaarheid van de wereldwijde verklaring voor het identificeren
bijwerkingen.

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


Antwoord 8

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 zijn 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))

Uitvoer:

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]

Antwoord 9

Het blijkt dat het antwoord altijd eenvoudig is.

Hier is een kleine voorbeeldmodule met een eenvoudige manier om deze in een main-definitie weer te geven:

def five(enterAnumber,sumation):
    global helper
    helper  = enterAnumber + sumation
def isTheNumber():
    return helper

Zo toon je het in een main-definitie:

import TestPy
def main():
    atest  = TestPy
    atest.five(5,8)
    print(atest.isTheNumber())
if __name__ == '__main__':
    main()

Deze eenvoudige code werkt precies zo en wordt uitgevoerd. Ik hoop dat het helpt.


Antwoord 10

Wat je zegt is om de methode als volgt te gebruiken:

globvar = 5
def f():
    var = globvar
    print(var)
f()  # Prints 5

Maar de betere manier is om de globale variabele als volgt te gebruiken:

globvar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

Beide geven dezelfde output.


Antwoord 11

Je moet verwijzen naar de globale variabele in elke functie die je 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]
"""

Antwoord 12

Je slaat de global niet echt op in een lokale variabele, maar maakt alleen een lokale verwijzing naar hetzelfde object waarnaar je originele globale verwijzing verwijst. Onthoud dat vrijwel alles in Python een naam is die verwijst naar een object, en niets wordt gekopieerd in de gebruikelijke bewerking.

Als je niet expliciet hoeft op te geven wanneer een identifier naar een vooraf gedefinieerde globale moet verwijzen, dan zou je waarschijnlijk expliciet moeten specificeren wanneer een identifier een nieuwe lokale variabele is (bijvoorbeeld met iets als de ‘ var’ commando gezien in JavaScript). Aangezien lokale variabelen vaker voorkomen dan globale variabelen in elk serieus en niet-triviaal systeem, is het systeem van Python in de meeste gevallen logischer.

Je zoueen taal kunnen hebben die probeerde te raden, met behulp van een globale variabele als die bestond of een lokale variabele aanmaakte als die niet bestond. Dat zou echter zeer foutgevoelig zijn. Het importeren van een andere module kan bijvoorbeeld onbedoeld een globale variabele met die naam introduceren, waardoor het gedrag van uw programma verandert.


Antwoord 13

Probeer dit:

def x1():
    global x
    x += 1
    print('x1: ', x)
def x2():
    global x
    x = x+1
    print('x2: ', x)
x = 5
print('x:  ', x)
x1()
x2()
# Output:
# x:   5
# x1:  6
# x2:  7

Antwoord 14

Als je een lokale variabele met dezelfde naam hebt, kun je de globals()functie.

globals()['your_global_var'] = 42

Antwoord 15

Gebruik in navolging van en als add-on een bestand met alle globale variabelen die allemaal lokaal zijn gedeclareerd en import as:

bestand initval.py :

Stocksin = 300
Prices = []

Bestand GETSTOCKS.PY :

import initval as iv
def getmystocks(): 
    iv.Stocksin = getstockcount()
def getmycharts():
    for ic in range(iv.Stocksin):

Antwoord 16

Schrijven naar expliciete elementen van een globale array heeft blijkbaar niet de wereldwijde verklaring nodig, hoewel het schrijven van het “groothandel” dat vereiste heeft:

import numpy as np
hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])
def func1():
    global hostValue    # mandatory, else local.
    hostValue = 2.0
def func2():
    global hostValue    # mandatory, else UnboundLocalError.
    hostValue += 1.0
def func3():
    global hostArray    # mandatory, else local.
    hostArray = np.array([14., 15.])
def func4():            # no need for globals
    hostArray[0] = 123.4
def func5():            # no need for globals
    hostArray[1] += 1.0
def func6():            # no need for globals
    hostMatrix[1][1] = 12.
def func7():            # no need for globals
    hostMatrix[0][0] += 0.33
func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix

Antwoord 17

Referentie de klasse-naamruimte waar u wilt dat de wijziging verschijnt.

In dit voorbeeld gebruikt Runner Max uit de bestandsconfiguratie. Ik wil dat mijn test de waarde van max wijzigen wanneer runner het gebruikt.

hoofd / config.py

max = 15000

hoofd / runner.py

from main import config
def check_threads():
    return max < thread_count 

tests / runner_test.py

from main import runner                # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
   def test_threads(self):
       runner.max = 0                  # <----- 2. set global 
       check_threads()

Antwoord 18

Ik voeg dit toe zoals ik het niet heb gezien in een van de andere antwoorden en het kan nuttig zijn voor iemand die worstelt met iets dergelijks. globals()FUNCTION retourneert een mutable globaal Symboolwoordenboek waar u “magisch” gegevens beschikbaar kunt maken voor de rest van uw code.
Bijvoorbeeld:

from pickle import load
def loaditem(name):
    with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
        globals()[name] = load(openfile)
    return True

en

from pickle import dump
def dumpfile(name):
    with open(name+".dat", "wb") as outfile:
        dump(globals()[name], outfile)
    return True

Hiermee kun je variabelen uit en in de globale naamruimte dumpen/laden. Super handig, geen poespas, geen poespas. Vrij zeker dat het alleen Python 3 is.


Antwoord 19

Globals zijn prima – Behalve met Multiprocessing

Globaal in verband met multiprocessing op verschillende platforms/omgevingen
omdat Windows/Mac OS aan de ene kant en Linux aan de andere kant lastig zijn.

Ik zal je dit laten zien met een eenvoudig voorbeeld dat wijst op een probleem dat ik enige tijd geleden tegenkwam.

Als je wilt begrijpen waarom dingen anders zijn op Windows/MacO’s en Linux, moet je
moet weten, het standaardmechanisme om een nieuw proces te starten op …

  • Windows/MacOs is ‘spawn’
  • Linux is ‘vork’

Ze zijn verschillend in geheugentoewijzing en initialisatie … (maar ik ga hier niet op in
hier).

Laten we eens kijken naar het probleem/voorbeeld …

import multiprocessing
counter = 0
def do(task_id):
    global counter
    counter +=1
    print(f'task {task_id}: counter = {counter}')
if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)
    task_ids = list(range(4))
    pool.map(do, task_ids)

Vensters

Als je dit op Windows uitvoert (en ik veronderstel ook op MacOS), krijg je de volgende uitvoer …

task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4

Linux

Als je dit op Linux uitvoert, krijg je in plaats daarvan het volgende.

task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1

Antwoord 20

Er zijn 2 manieren om een variabele als globaal te declareren:

1. wijs variabele interne functies toe en gebruik globale regel

def declare_a_global_variable():
    global global_variable_1
    global_variable_1 = 1
# Note to use the function to global variables
declare_a_global_variable() 

2. wijs variabele externe functies toe:

global_variable_2 = 2

Nu kunnen we deze gedeclareerde globale variabelen gebruiken in de andere functies:

def declare_a_global_variable():
    global global_variable_1
    global_variable_1 = 1
# Note to use the function to global variables
declare_a_global_variable() 
global_variable_2 = 2
def print_variables():
    print(global_variable_1)
    print(global_variable_2)
print_variables() # prints 1 & 2

Opmerking 1:

Als u een globale variabele binnen een andere functie zoals update_variables()wilt wijzigen, moet u de globale regel in die functie gebruiken voordat u de variabele toewijst:

global_variable_1 = 1
global_variable_2 = 2
def update_variables():
    global global_variable_1
    global_variable_1 = 11
    global_variable_2 = 12 # will update just locally for this function
update_variables()
print(global_variable_1) # prints 11
print(global_variable_2) # prints 2

Opmerking 2:

Er is een uitzondering voor opmerking 1 voor lijst- en woordenboekvariabelen terwijl er geen globale regel in een functie wordt gebruikt:

# declaring some global variables
variable = 'peter'
list_variable_1 = ['a','b']
list_variable_2 = ['c','d']
def update_global_variables():
    """without using global line"""
    variable = 'PETER' # won't update in global scope
    list_variable_1 = ['A','B'] # won't update in global scope
    list_variable_2[0] = 'C' # updated in global scope surprisingly this way
    list_variable_2[1] = 'D' # updated in global scope surprisingly this way
update_global_variables()
print('variable is: %s'%variable) # prints peter
print('list_variable_1 is: %s'%list_variable_1) # prints ['a', 'b']
print('list_variable_2 is: %s'%list_variable_2) # prints ['C', 'D']

Antwoord 21

Hoewel dit is beantwoord, geef ik opnieuw een oplossing als ik de voorkeur geven aan een enkele lijn
Dit is als u globale variabele binnen de functie wilt maken

def someFunc():
    x=20
    globals()['y']=50
someFunc() # invoking function so that variable Y is created globally 
print(y) # output 50
print(x) #NameError: name 'x' is not defined as x was defined locally within function

Other episodes