Compléments Python
I. Variables locales et globales⚓︎
Les variables globales⚓︎
Définition
- Une variable globale est une variable déclarée en dehors de toutes les fonctions.
- Elle est accessible depuis n'importe quelle partie du code après sa déclaration.
Portée
La portée d'une variable globale est l'ensemble du module (fichier) dans lequel elle est définie. Elle peut être lue par n'importe quelle fonction dans ce module. Elle peut être modifiée par n'importe quelle fonction dans ce module si elle est mutable ou si elle est explicitement déclarée dans la fonction avec le mot-clé global
.
Utilisation
Les variables globales sont souvent utilisées pour stocker des informations qui doivent être partagées entre plusieurs fonctions ou parties du programme.
Les variables Locales⚓︎
Définition
Une variable locale est une variable déclarée à l'intérieur d'une fonction. Elle n'est accessible qu'à l'intérieur de cette fonction.
Si on assigne une variable dans une fonction (ma_variable =
) celle-ci est locale.
Attention, si on assigne une variable à l'intérieur d'une fonction, qui porte le même nom qu'une variable globale, cela peut rendre difficile la lecture et la compréhension du code.
Portée
La portée d'une variable locale est limitée à la fonction dans laquelle elle est définie. Une fois l'exécution de la fonction terminée, la variable locale est détruite.
Utilisation
Les variables locales sont utilisées pour stocker des informations temporaires qui ne sont nécessaires que dans le contexte d'une fonction particulière.
Inconvénients à l'utilisation d'une variable globale⚓︎
À savoir
Les variables globales peuvent être modifiées n’importe où dans le programme, ce qui rend le suivi des changements difficile. Cela peut compliquer la compréhension et la maintenance du code.
Une modification d’une variable globale dans une partie du code peut avoir des effets inattendus ailleurs.
Si on veut vraiment utiliser une variable globale, il faut lui donner le nom le plus explicite possible pour minimiser la possibilité que ce nom soit utilisé ailleurs dans le fichier et ajouter des commentaires expliquant son rôle.
Exemple 1⚓︎
Exercice 1
1. Exécuter le script ci-dessous. Que se passe-t-il ?
Solution
Dans la fonction gagne
, score
est une variable locale qui n'a pas été assignée :
À la lecture du code de la fonction, l’instruction score = ...
entraine la création d’une variable locale score sans valeur précisée. Ensuite à l’exécution de la fonction, pour procéder à l’affectation score = score + 10
, il faut évaluer score + 10
et pour cela évaluer score
qui est le nom d’une variable locale. Mais cette variable locale n’a pas de valeur.
2. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
score
n'a pas été assignée dans la fonction affiche
. Python recherche d'abord la variable dans l'espace de noms local. Si elle n'est pas trouvée localement, il cherche ensuite dans l'espace de noms global, et la trouve bien ici.
3. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
Ici la variable globale score
a bien été modifiée car dans la fonction l’instruction global score
signifie pour la fonction
que la variable score
utilisée n’est pas une variable locale mais est la variable globale.
4. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
La variable nbre
est locale dans la fonction augmente
. La variable globale score
n'est pas modifiée.
5. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
Ici le paramètre de la fonction augmente
est nommé score
.
La variable score
est locale dans la fonction augmente
. La variable globale score
n'est pas modifiée. Ces deux variables portent le même nom, mais ne sont pas du tout les mêmes. ⚠️ 🌵 À éviter absolument. Cela rend le code difficilement compréhensible alors que l’exécution de cette fonction produit exactement les mêmes résultats que celle vu un peu plus haut.
score = 0
def augmente(nbre):
nbre = nbre + 10
augmente(score)
print(score)
6. Nous avons vu qu'il vallait mieux éviter l'utilisation des variables globales. Modifier ci-dessous le code pour ne plus en avoir. Exactement la même situation de jeu doit être reproduite.
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
def affiche(note):
print(note) # score est une variable globale
def gagne(note):
return note + 10
def perd(note):
return note - 10
score = 0
affiche(score)
score = gagne(score)
affiche(score)
score = gagne(score)
affiche(score)
score = perd(score)
affiche(score)
Exemple 2⚓︎
Exercice 2
1. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
resultats
est une variable globale qui a été modifiée en place.
2. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
Dans la fonction ajoute_2
, resultats
est une variable locale qui n'a pas été assignée.
3. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
La variable resultats
dans la fonction ajoute_3
est une variable locale. Une nouvelle liste a été affectée à resultats
. La variable globale resultats
n'a pas été modifiée.
4. Ici le paramètre de la fonction ajoute_3
est nommé resultats
.
La variable resultats
est locale dans la fonction ajoute_3
, or il existe une variable globale resultats
. Ces deux variables portent le même nom, mais ne sont pas du tout les mêmes. Cela rend le code difficilement compréhensible.
Modifier le code ci-dessous pour éviter ce problème :
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
Exécuter le script ci-dessous. Répond-il à la question ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
Ce script ne répond pas à la question. resultats
n'a pas été modifié.
Exécuter le script ci-dessous, et vérifier qu'il répond bien à la question.
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
5. Pourquoi la fonction ajoute_4
se comporte-t-elle différemment de la fonction ajoute_3
?
Solution
- Dans la fonction
ajoute_3
on ama_liste = resultats
donc les deux noms désignent la même liste. Mais avecma_liste = ma_liste + [1]
une nouvelle listema_liste
a été créée. - Dans la fonction
ajoute_4
on ama_liste = resultats
donc les deux noms désignent la même liste. L'instructionma_liste.append(1)
modifie donc en placema_liste
etresultats
qui représentent la même liste. La variable globaleresultats
a donc été modifiée.
6. Nous avons vu qu'il vallait mieux éviter l'utilisation des variables globales. Modifier ci-dessous le code pour ne plus en avoir. Exactement la même situation doit être reproduite (ajout de 1
dans la liste à chaque fois que la fonction ajoute_5
est appelée)
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
def ajoute_5(ma_liste):
ma_liste.append(1)
return ma_liste
resultats = []
resultats = ajoute_5(resultats)
print(resultats)
II. La méthode append
⚓︎
Exercice 3
1. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
append
est une méthode qui modifie la liste mais ne renvoie rien (soit None
) donc ma_liste.append(1)
est une expression qui vaut None
. La fonction ajoute_6
renvoit donc None
, qui est affecté à resultats
.
2. Exécuter le script ci-dessous. Que se passe-t-il ?
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Solution
La fonction ajoute_6
renvoie donc None
, mais la liste resultats
a été modifiée en place.
⚠️ 🌵 Ce n'est pas du tout une bonne pratique de procéder ainsi, et il ne faut pas le faire.
👉 Il faut préférer :
def ajoute_5(ma_liste):
ma_liste.append(1)
return ma_liste
III. L'opérateur +=
⚓︎
Cas des nombres ou des chaînes de caractères
Pour les nombres, les chaînes de caractères ou les tuples : s = s + v
est équivalent à s += v
Code 1
Exécuter le script ci-dessous.
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Code 2
Exécuter le script ci-dessous.
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Cas des listes
ma_liste += [4]
se comporte commema_liste.append(4)
. L'opérateur+=
modifie la liste en placema_liste = ma_liste + [4]
crée une nouvelle liste qui est le résultat de la concaténation dema_liste
et[4]
. La liste originale n'est pas modifiée en place.- Remarquons que
ma_liste += [4, 5, 6]
est l'équivalent dema_liste.extend([4, 5, 6])
. La listema_liste
est aussi modifiée en place.
Doncma_liste += [4]
est équivalent àma_liste.extend([4])
Que se passe-t-il dans le Code 1 et dans le Code 2 ?
👉 Dans le Code 1
ma_liste = [1, 2, 3]
: Une liste est créée avec les éléments[1, 2, 3]
.- Appel de la fonction
ajouter_element
. La fonction est appelée avecma_liste
comme argument :ajouter_element(ma_liste)
:. - Modification de la liste dans la fonction :
ma_liste = ma_liste + [4]
: Cette ligne crée une nouvelle liste qui est le résultat de la concaténation dema_liste
et[4]
. La nouvelle liste[1, 2, 3, 4]
est assignée à la variable localema_liste
à l'intérieur de la fonction. Cette opération ne modifie pas la liste originale passée en argument, mais crée une nouvelle liste locale à la fonction. print(ma_liste)
: La liste originalema_liste
n'a pas été modifiée par la fonctionajouter_element
, donc il s'affiche[1, 2, 3]
.
👉 Dans le Code 2
ma_liste = [1, 2, 3]
: Une liste est créée avec les éléments[1, 2, 3]
.- Appel de la fonction
ajouter_element
. La fonction est appelée avecma_liste
comme argument :ajouter_element(ma_liste)
: - Modification de la liste dans la fonction :
ma_liste += [4]
: Cette ligne utilise l'opérateur+=
pour ajouter[4]
àma_liste
ce qui modifie la liste en place. - Les listes sont des objets mutables et la méthode
append
opère une mutation de la liste sans en créer une nouvelle. Or la variable locale et la variable globale désignent la même liste. La différence dans le code 1 est que la variable locale et la globale désignent aussi la même liste au début, mais après l’affectionliste = liste + [4]
, la variable locale désigne une autre liste. print(ma_liste)
: Après l'appel de la fonctionajouter_element
,ma_liste
a été modifiée pour inclure l'élément4
, donc il s'affiche[1, 2, 3, 4]
.
Bonne pratique
- Il vaut mieux utiliser les méthodes
append
ouextend
pour modifier une liste en place, l'opérateur+
pour créer une nouvelle liste. - Il vaut mieux éviter d'utiliser l'opérateur
+=
avec des listes.
IV. QCM récapitulatif⚓︎
QCM mutabilité et variables globales/locales
Cocher la bonne réponse (cercles) ou les deux bonnes réponses (carrés)
-
Qu'est-ce qu'une variable globale ?
- Une variable définie à l'intérieur d'une fonction
- Une variable définie en dehors de toutes les fonctions
- Une variable qui ne peut être utilisée que dans une seule fonction
- Une variable qui est automatiquement supprimée après son utilisation
-
Comment déclare-t-on une variable globale à l'intérieur d'une fonction ?
-
En utilisant le mot-clé
local
-
En utilisant le mot-clé
global
-
En utilisant le mot-clé
static
-
En utilisant le mot-clé
public
-
En utilisant le mot-clé
-
Quelle est la portée d'une variable locale ?
- Elle est accessible partout dans le programme
- Elle est accessible uniquement dans la fonction où elle est définie et dans les sous-fonctions qui y sont définies.
- Elle est accessible dans toutes les fonctions
- Elle est accessible uniquement en dehors des fonctions
-
Que se passe-t-il si vous essayez d'accéder à une variable locale en dehors de la fonction où elle est définie, ou en dehors d'une de ses sous-fonctions ?
- Le programme s'exécute normalement
-
Une erreur
NameError
est levée - La variable est automatiquement convertie en variable globale
- La variable prend une valeur par défaut
-
Que s'affiche-t-il ?
x = 10 def modifier_variable(): global x x = 20 modifier_variable() print(x)
- 10
- 20
-
Erreur
NameError
-
Erreur
SyntaxError
-
Que s'affiche-t-il ?
ma_liste = [1, 2, 3] def ajouter_element(): ma_liste.append(4) ajouter_element() print(ma_liste)
-
[1, 2, 3]
-
[1, 2, 3, 4]
-
Erreur
NameError
-
Erreur
UnboundLocalError
-
-
Que s'affiche-t-il ?
ma_liste = [1, 2, 3] def modifier_liste(): ma_liste = [4, 5, 6] modifier_liste() print(ma_liste)
-
[1, 2, 3]
-
[4, 5, 6]
-
Erreur
NameError
-
Erreur
UnboundLocalError
-
-
Que s'affiche-t-il ?
def modifier_liste(ma_liste): ma_liste = [7, 8, 9] return ma_liste ma_liste = [1, 2, 3] modifier_liste(ma_liste) print(ma_liste)
-
[1, 2, 3]
-
[7, 8, 9]
-
[1, 2, 3, 7, 8, 9]
-
Erreur
UnboundLocalError
-
-
Que s'affiche-t-il ?
def ajouter_element(ma_liste): ma_liste += [4] ma_liste = [1, 2, 3] ajouter_element(ma_liste) print(ma_liste)
-
[1, 2, 3]
-
[1, 2, 3, 4]
-
Erreur
NameError
-
Erreur
UnboundLocalError
-
-
Que s'affiche-t-il ?
x = [1, 2, 3] def modifier_variable(): x = [4, 5, 6] print(x) modifier_variable() print(x)
-
[4, 5, 6] [4, 5, 6]
-
[4, 5, 6] [1, 2, 3]
-
[1, 2, 3] [1, 2, 3]
-
[1, 2, 3] [4, 5, 6]
-
-
Que s'affiche-t-il ?
def modifier_liste(ma_liste): ma_liste.append(4) ma_liste = [5, 6, 7] ma_liste = [1, 2, 3] modifier_liste(ma_liste) print(ma_liste)
-
[1, 2, 3]
-
[1, 2, 3, 4]
-
[5, 6, 7]
-
[1, 2, 3, 5, 6, 7]
-
-
Que s'affiche-t-il ?
def func(): w = s + 42 s = 0 func() print(s)
- 0
- 42
-
Erreur
NameError
-
UnboundLocalError
-
Que s'affiche-t-il ?
def func(): s += 42 s = 0 func() print(s)
- 0
- 42
-
Erreur
NameError
-
UnboundLocalError
-
Que s'affiche-t-il ?
def func(a): a = a + 42 s = 0 func(s) print(s)
- 0
- 42
-
Erreur
NameError
-
UnboundLocalError
-
Que s'affiche-t-il ?
def func(a): a += 42 s = 0 func(s) print(s)
- 0
- 42
-
Erreur
NameError
-
UnboundLocalError
-
Que s'affiche-t-il ?
def func(s): s = s + 42 s = 0 func(s) print(s)
- 0
- 42
-
Erreur
NameError
-
UnboundLocalError
-
Que s'affiche-t-il ? Pourquoi ?
def func(): lst.append('hein?') lst = ['hoho...'] func() print(lst)
-
['hoho...', 'hein?']
-
['hoho...']
-
Erreur
NameError
-
UnboundLocalError
- Mutation de la variable globale.
-
La variable
lst
est inconnue dans la fonction.
-
-
Que s'affiche-t-il ? Pourquoi ?
def func(): lst = ['hein?'] lst = ['hoho...'] func() print(lst)
-
['hoho...']
-
['hein?']
-
Une variable locale
lst
a été créée, la variable globale n'a pas été modifiée. - La variable globale a été modifiée.
-
-
Que s'affiche-t-il ? Pourquoi ?
def func(lst): lst.append('hein?') ma_liste = ['hoho...'] func(ma_liste) print(ma_liste)
-
['hoho...']
-
['hoho...', 'hein?']
-
['hein?']
-
Mutation de la variable locale qui est l'argument passé à la fonction. Puisque les listes sont des objets mutables, toute modification de
lst
à l’intérieur de la fonction affecte également la liste originale en dehors de la fonction : (Python Tutor)
-
-
Que s'affiche-t-il ? Pourquoi ?
def func(lst): lst = ['hein?'] ma_liste = ['hoho...'] func(ma_liste) print(ma_liste)
-
['hoho...']
-
['hein?']
-
Une variable locale
lst
a été créée, la variable globale n'a pas été modifiée. -
La variable globale
ma_liste
a été modifiée.
-
-
Que s'affiche-t-il ? Pourquoi ?
def func(lst): lst += ['hein?'] ma_liste = ['hoho...'] func(ma_liste) print(ma_liste)
-
['hoho...']
-
['hoho...', 'hein?']
-
Mutation de la variable locale qui est l'argument passé à la fonction. Puisque les listes sont des objets mutables, toute modification de
lst
à l’intérieur de la fonction affecte également la liste originale en dehors de la fonction : (Python Tutor)
-
V. Crédits⚓︎
Avec l'aide judicieuse de Serge Bays et de Frédéric Zinelli.
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)