web-dev-qa-db-fra.com

Python variables globales de fonction?

Je sais que je devrais au départ éviter d'utiliser des variables globales en raison d'une telle confusion, mais si je devais les utiliser, la manière suivante est-elle un moyen valable de les utiliser? (J'essaie d'appeler la copie globale d'une variable créée dans une fonction distincte.)

x = "somevalue"

def func_A ():
   global x
   # Do things to x
   return x

def func_B():
   x=func_A()
   # Do things
   return x

func_A()
func_B()

Le 'x' utilisé par la deuxième fonction a-t-il la même valeur que la copie globale de 'x' que celle utilisée par 'func_a'? Lors de l'appel des fonctions après la définition, l'ordre est-il important?

246
Akshat Shekhar

Si vous voulez simplement accéder à une variable globale, utilisez simplement son nom. Cependant, pour changer sa valeur, vous devez utiliser le mot-clé global .

Par exemple.

global someVar
someVar = 55

Cela changerait la valeur de la variable globale en 55. Sinon, il suffirait d'affecter 55 à une variable locale.

L'ordre des listes de définitions de fonctions n'a pas d'importance (en supposant qu'elles ne se référent pas les unes aux autres), mais l'ordre dans lequel elles s'appellent.

375
Levon

Dans une portée Python, toute affectation à une variable non déjà déclarée dans cette étendue crée une nouvelle variable locale sauf si cette variable est déclarée précédemment dans la fonction comme faisant référence à une variable globalement portée. avec le mot clé global.

Regardons une version modifiée de votre pseudocode pour voir ce qui se passe:

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'

def func_A():
  # The below declaration lets the function know that we
  #  mean the global 'x' when we refer to that variable, not
  #  any local one

  global x
  x = 'A'
  return x

def func_B():
  # Here, we are somewhat mislead.  We're actually involving two different
  #  variables named 'x'.  One is local to func_B, the other is global.

  # By calling func_A(), we do two things: we're reassigning the value
  #  of the GLOBAL x as part of func_A, and then taking that same value
  #  since it's returned by func_A, and assigning it to a LOCAL variable
  #  named 'x'.     
  x = func_A() # look at this as: x_local = func_A()

  # Here, we're assigning the value of 'B' to the LOCAL x.
  x = 'B' # look at this as: x_local = 'B'

  return x # look at this as: return x_local

En fait, vous pourriez réécrire tout le nom de func_B avec la variable nommée x_local et le travail serait identique.

L'ordre n'a d'importance que dans l'ordre dans lequel vos fonctions effectuent des opérations qui modifient la valeur du x global. Ainsi, dans notre exemple, l'ordre n'a pas d'importance, puisque func_B appelle func_A. Dans cet exemple, l'ordre compte:

def a():
  global foo
  foo = 'A'

def b():
  global foo
  foo = 'B'

b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.

Notez que global n'est requis que pour modifier les objets globaux. Vous pouvez toujours y accéder depuis une fonction sans déclarer global. Ainsi, nous avons:

x = 5

def access_only():
  return x
  # This returns whatever the global value of 'x' is

def modify():
  global x
  x = 'modified'
  return x
  # This function makes the global 'x' equal to 'modified', and then returns that value

def create_locally():
  x = 'local!'
  return x
  # This function creates a new local variable named 'x', and sets it as 'local',
  #  and returns that.  The global 'x' is untouched.

Notez la différence entre create_locally et access_only - access_only accède au x global bien qu’il n’ait pas appelé global, et même si create_locally n’utilise pas global non plus, il crée une copie locale puisqu'il s'agit de attribution une valeur.

La confusion ici est la raison pour laquelle vous ne devriez pas utiliser de variables globales.

102
jdotjdot

Comme d'autres l'ont noté, vous devez déclarer une variable global dans une fonction lorsque vous souhaitez que cette fonction puisse modifier la variable globale. Si vous souhaitez uniquement y accéder, vous n'avez pas besoin de global.

Pour entrer un peu plus dans le détail, "modifier" signifie: si vous voulez relier de nouvea le nom global afin qu'il pointe vers un objet différent, le nom doit être déclaré global dans la fonction.

De nombreuses opérations qui modifient (transforment) un objet ne le font pas associent à nouveau le nom global pour pointer vers un autre objet. Elles sont donc toutes valides sans déclarer le nom global dans la fonction.

d = {}
l = []
o = type("object", (object,), {})()

def valid():     # these are all valid without declaring any names global!
   d[0] = 1      # changes what's in d, but d still points to the same object
   d[0] += 1     # ditto
   d.clear()     # ditto! d is now empty but it`s still the same object!
   l.append(0)   # l is still the same list but has an additional member
   o.test = 1    # creating new attribute on o, but o is still the same object
17
kindall

Voici un cas qui m'a surpris, en utilisant un global comme valeur par défaut d'un paramètre.

globVar = None    # initialize value of global variable

def func(param = globVar):   # use globVar as default value for param
    print 'param =', param, 'globVar =', globVar  # display values

def test():
    global globVar
    globVar = 42  # change value of global
    func()

test()
=========
output: param = None, globVar = 42

Je m'attendais à ce que param ait une valeur de 42. Surprise. Python 2.7 a évalué la valeur de globVar lors de la première analyse de la fonction func. Changer la valeur de globVar n'affectait pas la valeur par défaut assignée à param. Retarder l'évaluation, comme dans ce qui suit, a fonctionné comme j'en avais besoin.

def func(param = eval('globVar')):       # this seems to work
    print 'param =', param, 'globVar =', globVar  # display values

Ou, si vous voulez être en sécurité,

def func(param = None)):
    if param == None:
        param = globVar
    print 'param =', param, 'globVar =', globVar  # display values
4
SoloPilot

Vous pouvez accéder directement à une variable globale dans une fonction. Si vous souhaitez modifier la valeur de cette variable globale, utilisez "nom_variable". Voir l'exemple suivant:

var = 1
def global_var_change():
      global var
      var = "value changed"
global_var_change() #call the function for changes
print var

De manière générale, ce n'est pas une bonne pratique de programmation. En brisant la logique de l'espace de noms, le code peut devenir difficile à comprendre et à déboguer.

3
Noisy_Botnet

Vous devez utiliser la déclaration global lorsque vous souhaitez modifier la valeur affectée à une variable globale.

Vous n'en avez pas besoin pour lire une variable globale. Notez que l'appel d'une méthode sur un objet (même si elle modifie les données de cet objet) ne modifie pas la valeur de la variable contenant cet objet (magie réflexive absente).

1
Marcin