web-dev-qa-db-fra.com

Pourquoi l'affectation à mes variables globales ne fonctionne-t-elle pas en Python?

J'ai de la difficulté à essayer de comprendre les règles de portée du python.

Avec le script suivant:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Donne la sortie inattendue (pour moi) de:

 Avant le setA 
 La valeur de a est 7 
 Dans la série A, a est maintenant 42 
 Après setA 
 La valeur de a est 7 

Où je m'attendrais à ce que la dernière impression de la valeur de a soit 42 et non 7. Que me manque-t-il à propos des règles de portée de Python pour la portée des variables globales?

57
Free Wildebeest

Les variables globales sont spéciales. Si vous essayez d'affecter une variable a = value à l'intérieur d'une fonction, une nouvelle variable locale est créée dans la fonction, même s'il existe une variable globale du même nom. Pour accéder à la variable globale, ajoutez une instruction global à l'intérieur de la fonction:

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

Voir aussi Nommer et lier pour une explication détaillée des règles de nommage et de liaison de Python.

110
Adam Rosenfield

L'astuce pour comprendre cela est que lorsque vous affectez une variable en utilisant =, vous la déclarez également en tant que variable locale. Ainsi, au lieu de changer la valeur de la variable globale a, setA (valeur) définit en fait une variable locale (appelée par la suite a) sur la valeur transmise.

Cela devient plus évident si vous essayez d’afficher la valeur de a au début de setA (valeur) comme suit:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

Si vous essayez d’exécuter ce logiciel, Python vous donnera une erreur utile:

 Traceback (dernier appel passé): 
 Fichier "scopeTest.py", ligne 14, dans 
 setA (42) 
 Fichier "scopeTest.py", ligne 7, dans setA 
 print "Avant l'affectation, a est% d"% (a) 
 UnboundLocalError: variable locale 'a' référencée avant l'affectation 

Cela nous indique que Python a décidé que la fonction setA (valeur) avait une variable locale appelée a, qui correspond à ce que vous modifiez lorsque vous l'attribuez dans la fonction. Si vous n'affectez pas à a dans la fonction (comme avec printA ()), Python utilise la variable globale A.

Pour marquer une variable comme globale, vous devez utiliser le mot clé global en Python, dans l'étendue pour laquelle vous souhaitez utiliser la variable globale . Dans ce cas, cela fait partie de la fonction setA (valeur). Alors le script devient:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Cet ajout d'une ligne indique à Python que, lorsque vous utilisez la variable a dans la fonction setA (valeur), vous parlez de la variable globale et non d'une variable locale.

12
Free Wildebeest

Python n'a pas de concept de variable comme les autres langages. Vous avez des objets qui sont "quelque part" et vous avez des références à ces objets. = est utilisé pour assigner ces objets à des références dans l'espace de noms current .

Vous créez un nom a dans l'espace de nom de la fonction setA qui fait référence à l'objet auquel la valeur fait référence.

1
DasIch

dans la fonction, a est traité comme une variable locale, vous devez définir 

un global 

à l'intérieur de la fonction

1
appusajeev

L'exécution d'une fonction introduit une nouvelle table de symboles utilisée pour les variables locales de la fonction. Plus précisément, toutes les affectations de variables dans une fonction stockent la valeur dans la table des symboles locale; alors que les références de variable regardent d’abord dans la table de symboles locale, puis dans les tables de symboles locales des fonctions englobantes, puis dans la table de symboles globale et enfin dans la table des noms intégrés. Ainsi, il n'est pas possible d'affecter directement une valeur au sein d'une fonction aux variables globales (à moins que celles-ci ne soient nommées dans une instruction globale), bien qu'elles puissent être référencées.

0
Nilesh Jain