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