web-dev-qa-db-fra.com

Utiliser des variables globales dans une fonction

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?

2870
user46646

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.

3964
Paul Stephenson

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

732
Jeff Shannon

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
201
gimel

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.

84

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.

55
J S

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?.

42
Rauni Lillemets

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

Utilisation de globals sans modification

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!!!'

Modification de la variable globale depuis une fonction

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.

Variables locales du même nom

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.

37
Aaron Hall

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]
31
Bohdan

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.

22
user2876408

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.

21
gxyd

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]
"""
20
Mohamed El-Saka

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.

18
Kylotan

Essaye ça:

def x1():
    global x
    x = 6

def x2():
    global x
    x = x+1
    print x

x = 5
x1()
x2()  # output --> 7
15
Sagar Mehta

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):
12
user5473311

Si vous avez une variable locale portant le même nom, vous pouvez utiliser la fonction globals() .

globals()['your_global_var'] = 42
12
Martin Thoma

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
11
Mike Lampton

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.

5
Rafaël Dera

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()
5
llewellyn falco