Variable locale, variable globale

Voici une fonction pas très utile :

In [1]:
def retourne_un():
    x = 1
    return x
In [2]:
retourne_un()
Out[2]:
1

On dit que x est une variable locale. Elle est définie à l'intérieur de la fonction.

Ci-dessous, la variable x qui contient 7 est une variable globale :

In [3]:
x = 7

def retourne_un():
    x = 1
    return x

print(retourne_un())
print(x)
1
7

Lors de l'exécution de la fonction retourne_un, x est d'abord cherchée localement à l'intérieur de la fonction : 1

Lors du print(x), x est cherché dans le module courant : 7

Avantage : on peut utiliser des variables locales à l'intérieur des fonctions sans se soucier de leur nom : si une variable globale à l'extérieur de la fonction porte le même nom, la variable globale ne sera pas modifiée.

On peut utiliser une variable globale dans une fonction :

In [4]:
x = 7

def multiplie(n):
    return n*x

multiplie(10)
Out[4]:
70

Plus fort mais déconseillé : on peut modifier une variable globale dans une fonction :

In [5]:
x = 7

def bof(n):
    global x
    x = x+1
    return n*x

print(bof(10))
print(x)
80
8

C'est déconseillé car : dans un programme très long, où la fonction est écrite très loin de l'affectation de la variable, il est très difficile de s'y retrouver.

Exercice 1

Quelles sont les variables locales et globales ci-dessous ? Qu'affiche le programme ? Réfléchir puis exécuter le programme ci-dessous.

In [6]:
a = 1
b = 2

def f():
    b = 30
    c = 4
    return a + b + c

print(f())
print(a)
print(b)
35
1
2

Que se passe-t-il si on ajoute à la fin print(c) ?

In [7]:
a = 1
b = 2

def f():
    b = 30
    c = 4
    return a + b + c

print(f())
print(a)
print(b)
print(c)
35
1
2
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-01344239dd00> in <module>
     10 print(a)
     11 print(b)
---> 12 print(c)

NameError: name 'c' is not defined

La variable c est définie localement dans la fonction mais pas dans le bloc où est le print(c).

Exercice 2

Quelles sont les variables locales et globales ci-dessous ? Qu'affiche le programme ? Réfléchir puis exécuter le programme ci-dessous.

In [8]:
def fonction1(k):
    global x
    x = 2*x
    a = 2*x
    b = k + a
    return b

x = 5
a = 3
b = 1

print(x)
print(a)
print(b)
print(fonction1(10))
print(x)
print(a)
print(b)
5
3
1
30
10
3
1

Exercice 3

Quelles sont les variables locales et globales ci-dessous ? Qu'affiche le programme ? Réfléchir puis exécuter le programme ci-dessous.

In [9]:
def f(x):
    x = 5
    return x
x = 10
print(f(x))
print(x)
5
10

Tout semble normal...

Exercice 4

Quelles sont les variables locales et globales ci-dessous ? Qu'affiche le programme ? Réfléchir puis exécuter le programme ci-dessous.

In [10]:
def tri_liste(L):
    if L[0] > L[1]:
        aux = L[0]
        L[0] = L[1]
        L[1] = aux
    return L

L1 = [6,2]
print(tri_liste(L1))
print(L1)
[2, 6]
[2, 6]

Explication :

  • ligne 8 : la variable L1 pointe sur l'objet liste [6,2]
  • ligne 9 : on appelle la fonction tri_liste
    • le paramètre L est défini localement dans la fonction mais pointe vers le même objet que la variable L1 définie globalement (voir la fin : référence partagée)
    • l'objet liste est modifié : 6 et 2 sont échangés
    • après le return, la variable locale L de la fonction est détruite mais pas l'objet vers lequel elle pointait.
  • ligne 10 : la variable globale L1 pointe vers l'objet liste qui a été modifié

Exercice 5

Pour bien comprendre ce qui s'est passé aux exercices 3 et 4, copier le code de l'exercice 3, le coller dans pythontutor.com, visualiser pas à pas l'exécution.

Faire de même avec le code de l'exercice 4.

règle LEG

In [11]:
x = 1
y = 2
z = 3

def f():
    x = 10
    y = 20
    def g():
        x = 100
        return x+y+z
    return g()
print(f())
print(x+y+z)
123
6

Lors de l'appel à la fonction g, les variables sont cherchées dans l'ordre LEG : Localement, puis dans la fonction Englobante, puis Globalement.

Dans g, pour calculé x+y+z,

  • x est trouvé localement : 100
  • y n'est pas trouvé localement mais est trouvé dans la fonction f englobante : 20
  • z n'est pas trouvé localement, pas dans la fonction englobante, mais est trouvé globalement : 3

Pour aller plus loin : référence partagée

In [12]:
a = 2
b = a

Les variables a et b pointent sur le même objet, l'entier 2.

In [13]:
a = 3
print(a,b)
3 2

a pointe maintenant sur l'objet 3 et b pointe toujours sur l'objet 2

Quelques problèmes se posent quand l'objet est mutable.

In [14]:
LA = [5, 8, 4]
LB = LA

Les variables LA et LB pointent vers le même objet liste [,,], une liste à trois places. La première place pointe sur l'objet 5, la deuxième sur 8, la troisième sur 4.

Si on modifie un des éléments :

In [15]:
LA[1] = 10
print(LA)
print(LB)
[5, 10, 4]
[5, 10, 4]

La deuxième place de la liste pointe maintenant sur 10.

Si on souhaite que LB ne soit pas modifiée, il faut faire une "shallow copy de la liste" : dans la mémoie, il n'y aura plus un seul objet liste mais deux.

In [16]:
LA = [5, 8, 4]
LB = LA[:]
LA[1] = 10
print(LA)
print(LB)
[5, 10, 4]
[5, 8, 4]
In [ ]:
 
In [ ]: