Jusqu'où ma variable est visible ?¶
La durée de vie ou la portée d'une variable commence lorsqu'elle est déclarée (à gauche d'un signe =) et finit à la fin du bloc où elle a été déclarée. Elle est visible à l'intérieur des sous-blocs du bloc.
Elle est visible à l'intérieur des fonctions qui sont appelées dans son bloc (c'est récursif).
Si un sous-bloc ou une fonction définit une variable du même nom, alors elle n'est plus visible jusqu'à la mort de la nouvelle variable (c'est la nouvelle variable qui est visible).
On appelle variables globales les variables qui sont dans le plus grand bloc (celui qui inclut tous les autres). Elles sont visibles de partout (sauf cas ci-dessus).
def f(x):
print(a,x) # a global défini juste avant l'appel f(3)
def g(x):
a = 2 # création d'un nouveau a
print(a,b,x) # prend le a le plus local, donc celui de g(x)
a = 1
f(3)
b = 10 # si cette ligne est commentée, g(x) va avoir un problème lors de l'affichage de b
g(11)
print(a) # seul le a global est visible ici
b = 12
1 3 2 10 11 1
def f1(x):
def f2(x):
a = 10
b = 2
print(a,b,x) # il s'agit du a de f2 et non celui de f1
a = 1
f2(x+1)
print(a,b) # ici b n'existe plus, il est mort à la fin de f2(x)
f1(2)
10 2 3 1 12
def f1(x):
a = 1
def f2(x):
a = a + 1 # erreur, j'utilise a locale à f2 (à droite du =) avant de l'avoir initialisé
# En effet le 2e a fait référence au a créé juste avant sur la même ligne
print(a,x)
f2(x+1)
print(a)
f1(4)
--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-3-bdb9286d9173> in <module>() 8 print(a) 9 ---> 10 f1(4) <ipython-input-3-bdb9286d9173> in f1(x) 5 # En effet le 2e a fait référence au a créé juste avant sur la même ligne 6 print(a,x) ----> 7 f2(x+1) 8 print(a) 9 <ipython-input-3-bdb9286d9173> in f2(x) 2 a = 1 3 def f2(x): ----> 4 a = a + 1 # erreur, j'utilise a locale à f2 (à droite du =) avant de l'avoir initialisé 5 # En effet le 2e a fait référence au a créé juste avant sur la même ligne 6 print(a,x) UnboundLocalError: local variable 'a' referenced before assignment
nonlocal¶
Il existe le mot clef nonlocal
qui permet d'indiquer que l'on fait référence à la première variable que l'on rencontre en remontant les niveaux de portée des variables mais en excluant les variables globales. Ainsi dans l'exemple ci-dessus
def f2(x):
nonlocal a
fonctionnerait car alors le a
aurait été celui de f1
.
def f1(x):
a = 1
def f2(x):
nonlocal a
a = a + 1
print(a,x)
f2(x+1)
print(a) # a été modifiée dans f2
f1(4)
2 5 2
Utiliser nonlocal
doit être fait avec discernement (comprendre à éviter). Dans notre cas il serait nettement préférable de passer a
en argument de f2
et de récupérer la nouvelle valeur.
global¶
Il existe aussi le mot clef global
qui permet de définir une variable globale au sein d'une fonction.
C'est là encore une mauvaise idée dans 99% des cas. Outre le fait qu'avoir des variables globales est à
éviter, définir une variable globale au sein d'une fonction risque d'entrer en collision avec une autre
fonction qui définie la même variable globale :
def f1():
global x
x = 10
def fois2(x):
return 2*x
x = 0
f1()
fois2(x)
20
Celui qui a écrit le programme principal va être surpris puisque la signature de la fonction f1
ne laisse pas entendre qu'elle touche à la variable x
.
Celui qui a écrit la fonction f1
voulait stocker x
globalement et n'a probablement pas pensé qu'on utiliserait ce nom de variable ailleurs.
Si vous avez besoin de variables globales utilisées par différentes fonctions, la bonne solution consiste à faire votre bibliothèque avec ces variables et vos fonctions (voir les Modules, tout dans un fichier, et les Paquets, une arborescence de fichiers pour tout ranger).
{{ PreviousNext("01 - Variables en mémoire.ipynb", "03 - Formatting.ipynb")}}