Comment créer ou utiliser une variable globale dans une fonction?
Si je crée une variable globale dans une fonction, comment puis-je utiliser cette variable globale dans une autre fonction? Dois-je stocker la variable globale dans une variable locale de la fonction qui nécessite son accès?
Vous pouvez utiliser une variable globale dans d'autres fonctions en la déclarant comme global
dans chaque fonction qui l'assigne:
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
J'imagine que la raison en est que, puisque les variables globales sont si dangereuses, Python veut s'assurer que vous savez vraiment ce à quoi vous jouez en demandant explicitement le mot-clé global
.
Voir les autres réponses si vous souhaitez partager une variable globale entre les modules.
Si je comprends bien votre situation, ce que vous voyez est le résultat de la façon dont Python gère les espaces de noms locaux (fonction) et globaux (module).
Dites que vous avez un module comme celui-ci:
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Vous vous attendez peut-être à imprimer 42, mais à la place 5. Comme il a déjà été mentionné, si vous ajoutez une déclaration 'global
' à func1()
, alors func2()
affichera 42.
def func1():
global myGlobal
myGlobal = 42
Ce qui se passe ici, c'est que Python suppose que tout nom attribué à , n'importe où dans une fonction, est local à cette fonction. sauf indication explicite contraire. S'il ne s'agit que de lire à partir d'un nom et que ce nom n'existe pas localement, il tentera de rechercher le nom dans toutes les portées contenant le contenu (par exemple: la portée globale du module).
Lorsque vous affectez le nom 42 au nom myGlobal
, Python crée donc une variable locale qui masque la variable globale du même nom. Ce local sort de la portée et est ramasse-miettes quand func1()
retourne; pendant ce temps, func2()
ne peut jamais rien voir d'autre que le nom global (non modifié). Notez que cette décision d'espace de noms se produit au moment de la compilation, pas au moment de l'exécution. Si vous lisiez la valeur de myGlobal
à l'intérieur de func1()
avant de l'assigner, vous obtiendrez un UnboundLocalError
, car Python a déjà décidé qu’il s’agissait d’une variable locale, mais aucune valeur n’y avait encore été associée. Mais en utilisant l'instruction 'global
', vous indiquez à Python qu'il doit chercher le nom ailleurs, au lieu de l'assigner localement.
(Je pense que ce comportement est dû en grande partie à une optimisation des espaces de noms locaux. Sans ce comportement, VM de Python aurait besoin d'effectuer au moins trois recherches de noms chaque fois qu'un nouveau nom est attribué à l'intérieur d'une fonction (à s’assurer que le nom n’existait pas déjà au niveau module/builtin), ce qui ralentirait considérablement une opération très courante.)
Vous voudrez peut-être explorer la notion de namespaces . En Python, le module est le lieu naturel pour des données globales :
Chaque module a sa propre table de symboles privée, qui est utilisée comme table de symboles globale par toutes les fonctions définies dans le module. Ainsi, l’auteur d’un module peut utiliser des variables globales dans le module sans se soucier des conflits accidentels avec les variables globales d’un utilisateur. D'autre part, si vous savez ce que vous faites, vous pouvez toucher les variables globales d'un module avec la même notation que celle utilisée pour faire référence à ses fonctions,
modname.itemname
.
Une utilisation spécifique de global-in-a-module est décrite ici - Comment partager des variables globales entre modules? , et pour que ce soit complet, le contenu est partagé ici:
Le moyen canonique de partager des informations entre les modules d’un même programme consiste à créer un module de configuration spécial (souvent appelé config ou . ) cfg ). Importez simplement le module de configuration dans tous les modules de votre application. le module devient alors disponible sous forme de nom global. Comme il n'y a qu'une seule instance de chaque module, toute modification apportée à l'objet module est reflétée partout. Par exemple:
Fichier: config.py
x = 0 # Default value of the 'x' configuration setting
Fichier: mod.py
import config config.x = 1
Fichier: main.py
import config import mod print config.x
Python utilise une heuristique simple pour décider de la portée à partir de laquelle charger une variable, entre local et global. Si un nom de variable apparaît à gauche d'une affectation, mais n'est pas déclaré global, il est supposé être local. S'il n'apparaît pas à gauche d'une affectation, il est supposé être global.
>>> 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
>>>
Voyez comment baz, qui apparaît à gauche d'une affectation dans foo()
, est la seule variable LOAD_FAST
.
Si vous souhaitez faire référence à une variable globale dans une fonction, vous pouvez utiliser le mot clé global pour déclarer les variables globales. Vous n'êtes pas obligé de l'utiliser dans tous les cas (comme le prétend quelqu'un, à tort): si le nom référencé dans une expression est introuvable dans la ou les étendues locales des fonctions dans lesquelles cette fonction est définie, elle est recherchée parmi les mots clés globaux. variables.
Toutefois, si vous affectez une nouvelle variable non déclarée comme globale dans la fonction, elle est implicitement déclarée comme locale et peut occulter toute variable globale existante portant le même nom.
En outre, les variables globales sont utiles, contrairement à certains OOP zélotes qui prétendent le contraire - en particulier pour les scripts plus petits, où OOP est excessif.
En plus des réponses déjà existantes et pour rendre cela plus déroutant:
En Python, les variables qui ne sont référencées que dans une fonction sont implicitement globales . Si une nouvelle valeur est affectée à une variable n'importe où dans le corps de la fonction, elle est supposée être un local . Si une nouvelle valeur est jamais affectée à une variable dans la fonction, elle est implicitement locale et vous devez la déclarer explicitement comme "globale".
Bien qu’un peu surprenant au début, un instant de considération l’explique. D'une part, imposer des variables globales pour les variables affectées constitue une barrière contre les effets secondaires non désirés. D'autre part, si global était requis pour toutes les références globales, vous utiliseriez global tout le temps. Vous devez déclarer globalement chaque référence à une fonction intégrée ou à un composant d’un module importé. Cet encombrement irait à l'encontre de l'utilité de la déclaration globale pour identifier les effets secondaires.
Source: Quelles sont les règles pour les variables locales et globales en Python?.
Si je crée une variable globale dans une fonction, comment puis-je utiliser cette variable dans une autre fonction?
Nous pouvons créer un global avec la fonction suivante:
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'
L'écriture d'une fonction ne lance pas son code. Nous appelons donc la fonction create_global_variable
:
>>> create_global_variable()
Vous pouvez simplement l'utiliser, tant que vous ne vous attendez pas à changer l'objet vers lequel il pointe:
Par exemple,
def use_global_variable():
return global_variable + '!!!'
et maintenant nous pouvons utiliser la variable globale:
>>> use_global_variable()
'Foo!!!'
Pour pointer la variable globale vers un autre objet, vous devez utiliser à nouveau le mot clé global:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Notez qu'après l'écriture de cette fonction, le code qui la modifie n'a toujours pas été exécuté:
>>> use_global_variable()
'Foo!!!'
Donc, après avoir appelé la fonction:
>>> change_global_variable()
nous pouvons voir que la variable globale a été changée. Le nom global_variable
pointe maintenant sur 'Bar'
:
>>> use_global_variable()
'Bar!!!'
Notez que "global" dans Python n'est pas vraiment global - il est uniquement global au niveau du module. Donc, il n'est disponible que pour les fonctions écrites dans les modules dans lesquels il est global. Les fonctions mémorisent le module dans lequel elles sont écrites. Par conséquent, lorsqu'elles sont exportées dans d'autres modules, elles recherchent toujours le module dans lequel elles ont été créées pour rechercher des variables globales.
Si vous créez une variable locale portant le même nom, une variable globale sera ombragée:
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!!!'
Mais utiliser cette variable locale mal nommée ne change pas la variable globale:
>>> use_global_variable()
'Bar!!!'
Notez que vous devriez éviter d'utiliser les variables locales portant le même nom que les variables globales, à moins de savoir précisément ce que vous faites et d'avoir une très bonne raison de le faire. Je n'ai pas encore rencontré une telle raison.
Avec l'exécution parallèle, les variables globales peuvent générer des résultats inattendus si vous ne comprenez pas ce qui se passe. Voici un exemple d'utilisation d'une variable globale dans le multitraitement. Nous pouvons clairement voir que chaque processus fonctionne avec sa propre copie de la variable:
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))
Sortie:
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]
Il se trouve que la réponse est toujours simple.
Voici un petit exemple de module avec un moyen simple de l'afficher dans une définition main
:
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Voici comment l'afficher dans une définition main
:
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __== '__main__':
main()
Ce code simple fonctionne comme ça, et il s'exécutera. J'espère que ça aide.
Ce que vous dites, c'est d'utiliser la méthode suivante:
globvar = 5
def f():
var = globvar
print(var)
f() # Prints 5
Mais le meilleur moyen consiste à utiliser la variable globale comme ceci:
globavar = 5
def f():
global globvar
print(globvar)
f() #prints 5
Les deux donnent la même sortie.
Vous devez référencer la variable globale dans chaque fonction que vous souhaitez utiliser.
Comme suit:
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]
"""
Vous ne stockez pas le global dans une variable locale, vous créez simplement une référence locale au même objet que votre référence globale d'origine. Rappelez-vous que presque tout dans Python est un nom qui fait référence à un objet, et rien n'est copié dans les opérations habituelles.
Si vous n'étiez pas obligé de spécifier explicitement quand un identifiant devait faire référence à un global prédéfini, vous devriez alors spécifier explicitement quand un identifiant est une nouvelle variable locale (par exemple, avec quelque chose comme la commande 'var' vu en JavaScript). Puisque les variables locales sont plus courantes que les variables globales dans tout système sérieux et non trivial, le système de Python est plus logique dans la plupart des cas.
Vous pouvez avez un langage qui tente de deviner, en utilisant une variable globale si elle existe ou en créant une variable locale si ce n’est pas le cas. Cependant, ce serait très sujet aux erreurs. Par exemple, l'importation d'un autre module peut introduire par inadvertance une variable globale portant ce nom, modifiant ainsi le comportement de votre programme.
Essaye ça:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
Ensuite, utilisez un fichier pour contenir toutes les variables globales, toutes déclarées localement, puis import as
:
Fichier initval.py:
Stocksin = 300
Prices = []
Fichier getstocks.py:
import initval as iv
def getmystocks():
iv.Stocksin = getstockcount()
def getmycharts():
for ic in range(iv.Stocksin):
Si vous avez une variable locale portant le même nom, vous pouvez utiliser la fonction globals()
.
globals()['your_global_var'] = 42
L'écriture sur des éléments explicites d'un tableau global n'a apparemment pas besoin de la déclaration globale, bien que l'écriture "en gros" impose cette exigence:
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
J'ajoute ceci car je ne l'ai pas vu dans aucune des réponses et cela pourrait être utile pour quelqu'un qui lutte avec quelque chose de similaire. La fonction globals()
renvoie un dictionnaire de symboles global modifiable dans lequel vous pouvez "magiquement" rendre des données disponibles pour le reste de votre code. Par exemple:
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
et
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
Vous permettra simplement de vider/charger des variables de et dans l'espace de noms global. Super pratique, pas de muss, pas de chichi. Je suis presque sûr que c'est Python 3 uniquement.
Référencez l'espace de noms de classe où vous souhaitez que les modifications apparaissent.
Dans cet exemple, le coureur utilise max à partir du fichier config. Je veux que mon test change la valeur de max quand le coureur l'utilise.
main/config.py
max = 15000
main/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()