La portée des variables

La portée des variables

Une variable peut être "connue" dans une partie d'un programme et inconnue dans une autre partie : la "zone" dans laquelle la variable est connue est la portée (en anglais : scope) de la variable.

Dans un même programme, deux variables peuvent avoir le même nom, pourvu que leur portée respective n'interfèrent pas.

Un premier exemple

On affecte une variable a dans la partie principale du programme. On appelle ensuite une fonction dans laquelle une variable a est affectée.



def f() :
	a=2
	print("Valeur de a dans le corps de la fonction : {} ".format(a))
	print()
	

a=5

print("Valeur de a dans la partie principale,")
print("avant appel de la fonction f : {}".format(a))
print()

f()
	
print("Valeur de a dans la partie principale,")
print("après appel de la fonction f : {}".format(a))

On obtient :

Valeur de a dans la partie principale,
avant appel de la fonction f : 5

Valeur de a dans le corps de la fonction : 2 

Valeur de a dans la partie principale,
après appel de la fonction f : 5

La variable a de la partie principale n'est pas affectée par l'instruction a=2 de la fonction.

Lorsque Python rencontre une telle assignation à l'intérieur d'une fonction, il crée une variable locale à la fonction, qui n'interfère pas avec la variable de même nom extérieure à la fonction.

En d'autres termes, tout se passe comme si le programme était le suivant :


def f() :
	b=2
	print("Valeur de b dans le corps de la fonction : {} ".format(b))
	print()
	

a=5

print("Valeur de a dans la partie principale,")
print("avant appel de la fonction f : {}".format(a))
print()

f()
	
print("Valeur de a dans la partie principale,")
print("après appel de la fonction f : {}".format(a))

Ce principe sera utilisé en permanence même sans y penser. Imaginez qu'un tel principe de portée n'existe pas : lorsqu'on écrit un gros programme, on devrait sans cesse se demander si le nom que l'on est en train d'introduire pour une simple petite routine est déjà utilisé ou non. Il est évident que l'on aurait très vite des erreurs et des variables interférant. Ou des noms de variables peu adaptés...

Un second exemple

On reprend ici l'idée du programme précédent et on cherche à modifier, dans la fonction f, la variable a de la partie principale.


def f() :
	a=a+3
	print("Valeur de a dans le corps de la fonction : {} ".format(a))
	print()
	

a=5

print("Valeur de a dans la partie principale,")
print("avant appel de la fonction f : {}".format(a))
print()

f()
	
print("Valeur de a dans la partie principale,")
print("après appel de la fonction f : {}".format(a))

On obtient :

File "prg.py"   in f
    a=a+3
UnboundLocalError: local variable 'a' referenced before assignment

Il est ainsi confirmé que la variable a de la partie principale ne peut pas être modifiée dans f.

Si l'on veut malgré tout que a soit modifiée par la fonction f, le mieux est d'utiliser un paramètre et une valeur de retour.

Par exemple :


def f(x) :
	x=x+3
	return x
	

a=5
print( 'Valeur de a : {}'.format(a) )
a=f(a)
print( 'Valeur de a : {}'.format(a) )

On obtient cette fois :

Valeur de a : 5
Valeur de a : 8

Exemple 3.

On a, malgré ce qui précède, le comportement suivant :


def f() :
	print("Valeur de a dans le corps de la fonction : {} ".format(a))
	print()
	

a=5

print("Valeur de a dans la partie principale,")
print("avant appel de la fonction f : {}".format(a))
print()

f()
	
print("Valeur de a dans la partie principale,")
print("après appel de la fonction f : {}".format(a))

qui donne :

 
Valeur de a dans la partie principale,
avant appel de la fonction f : 5

Valeur de a dans le corps de la fonction : 5 

Valeur de a dans la partie principale,
après appel de la fonction f : 5

Ainsi, dans le cas où l'on ne cherche pas à affecter une variable a localement à la fonction, la variable a globale semble connue (mais non disponible pour une affectation).

Le mot clef 'global'

Reprenons l'exemple précédent d'une tentative de modification d'une variable en-dehors de son espace.

Il est possible d'effectuer une telle modification en signifiant explicitement à python que l'on veut utiliser la variable définie dans la partie principale.


def f() :
	global a
	a=a+3
	print("Valeur de a dans le corps de la fonction : {} ".format(a))
	print()
	

a=5

print("Valeur de a dans la partie principale,")
print("avant appel de la fonction f : {}".format(a))
print()

f()
	
print("Valeur de a dans la partie principale,")
print("après appel de la fonction f : {}".format(a))

On obtient cette fois :

Valeur de a dans la partie principale,
avant appel de la fonction f : 5

Valeur de a dans le corps de la fonction : 8 

Valeur de a dans la partie principale,
après appel de la fonction f : 8

Attention : vous éviterez autant que possible l'utilisation d'une telle variable globale. L'usage du mot clef global dans vos programmes sera sanctionné, sauf cas très particulier que vous devrez être capable de justifier.

Pour compléter la lecture de ce cours, lisez la page du cours d'openclassroom sur le sujet.