Python Variables

Identification

Infoforall

6 - Variables dans Python


x = x + 1
x = x + 1 en math et en info, c'est pas pareil !

Nous allons en voir un peu plus sur les variables et donc la façon de stocker des informations pour les réutiliser plus tard.

calcul bizarre
Image issue de http://hcc-cs.weebly.com/variables.html

Cette image n'était qu'une première approche. Nous allons en apprendre plus sur la façon dont Python gère ces mystérieuses boîtes.

Enfin, nous verrons pourquoi Sauron L'Oeil Qui Voit Tout n'est pas le seul à pouvoir être développeur, même sur un projet de 300 000 lignes.

Sauron voit tout
L'Oeil de Sauron : Gif provenant de https://gifer.com

Logiciel nécessaire pour l'activité : Thonny

Evaluation : -

  questions -

  -

Exercices supplémentaires 🏠 : Exercices

Documents de cours PDF : .PDF

Sources latex : .TEX et entete.tex et licence.tex

Résumé : Version HTML ou fond blanc ou ou PDF (couleur ou gris)

1 - Règles de nommage

1.1 Toujours une minuscule initiale

Vous remarquerez que tous les noms utilisés sur mes variables commencent par une minuscule. Respectez cette habitude. Un nom qui commence par une majuscule, c'est pour autre chose qu'une variable.

1.2 Pas d'espace dans un nom de variable

L'espace ne peut pas faire partie des noms de variables pour la simple et bonne raison qu'il joue le rôle de caractères délimitateurs. Par contre, Python est sensible à la casse : il distingue les minuscules et les majuscules. Les variables toto et toTO désignent deux variables différentes.

Voici deux techniques usuelles pour les longs noms de variables.

  • snake_case : utiliser des underscores entre les mots (usuel en Python)
    • position_voiture
    • liste_ennemis
  • CamelCase : utiliser une majuscule pour séparer les mots.
    • positionVoiture
    • listeEnnemis
1.3 Toujours un nom explicite

Donnez à vos variables des noms explicites de plus d'une lettre : des noms permettant de savoir au premier coup d'oeil ce qu'elles contiennent. a, b, c, ce n'est pas forcément explicite.

N'utilisez jamais de variable dont le nom est l (L minuscule) : il est trop difficile à distinguer d'un I (I majuscule) !

Exemple : si une variable contient le nombre de paquets de chips à acheter, on pourrait prendre :

  • x. Non, pas explicite.
  • nombre_de_paquets_de_chips. Plutôt non, trop long.
  • nombre_paquets. Ok.
  • nb_paquets. Ok.
  • nb. Ok si il n'y a qu'un nombre de choses à compter.
1.4 Noms réservés

Vous avez déjà vu que certains noms ne doivent pas être donnés à vos programme : turtle.py, math.py...

De la même façon, il existe des noms réservés qu'on ne peut pas utiliser comme nom de variable car l'interpréteur Python les utilise déjà comme mots-clés lorsqu'il analyse le texte de votre script :

False class finally is return None continue for lambda try True def from nonlocal while and del global not with as elif if or yield assert else import pass break except in raise

LIEN EXTERNE VERS LA DOCUMENTATION PYTHON

1.5 Accents et caractères spéciaux

Python accepte n'importe quel caractère dans les noms de variables (à part l'espace !).

Néanmoins, n'utilisez que les caractères non accentués car certains langages de programmation ne permettent pas de placer de tels caractères.

D'ailleurs, vos variables et vos fonctions devront porter des noms anglais si vous continuez en informatique dans le supérieur. Pas d'accent donc.

2 - Utilisation de variables

Rappels des épisodes précédents :

(Rappel) 2.1 VARIABLE - Affectation

Affectation

Les variables servent à stocker des données.

une sorte de boite
Image issue de http://hcc-cs.weebly.com/variables.html

Le mécanisme d'affectation de variables consiste à créer une liaison entre un NOM et un CONTENU MEMOIRE.

1
a = 10

L'opérateur = permet de créer une variable nommée a et y stocker la valeur 10.

On peut représenter naïvement ce mécanisme comme une boite qui porte un NOM et dans laquelle on place le CONTENU associé.

Boite a contenant 10

Néanmoins, une affectation est simplement un moyen de faire la liaison entre un NOM et un CONTENU en mémoire :

une sorte de liaison
Notation dans les algorithmes

Notez bien que c'est le CONTENU 10 qu'on associe au NOM a : on va de la droite vers la gauche. C'est pour cela qu'on écrit a  10 dans les algorithmes.

Lecture du contenu via la console interactive

Pour obtenir le contenu d'une variable, il suffit de taper le nom de cette variable dans la console interactive. Nous verrons que cela n'est pas suffisant dans un programme.

(Rappel) 2.2 - VARIABLE - Incrémentation

Incrémenter veut dire modifier la valeur d'une variable en lui ajoutant une autre valeur.

Incrémenter de 1 veut dire qu'on augmente la valeur de 1 : 45 passe à 46.

Ce +1 est la valeur par défaut en l'absence d'information.

Incrémenter de 2 veut dire qu'on augmente la valeur de 2 : 45 passe à 47.

Incrémenter de -1 veut dire qu'on augmente la valeur de -1 : 45 passe à 44.

On dit plutôt décrémenter.

Pour incrémenter a de 1 : a = a + 1

  1. a = a + 1 : évaluer la valeur actuelle de a,
  2. a = a + 1 : évaluer (calculer) ce que donne cette valeur + 1 et
  3. a = a + 1 : affecter le résultat de cette évaluation à a.
1 2
a = 10 a = a + 1

En ligne 1, on associe 10 à a.

En ligne 2, on évalue a + 1, ce qui donne 11. On place ENSUITE ce résultat de 11 dans a : au final, a contient donc 11.

Nouveautés :

2.3 Expression - Instruction - Affectation

Expression

Une expression est un ensemble de valeurs associées à des opérateurs. L'interpréteur peut évaluer l'expression pour en fournir la valeur.

Une expression ne modifie pas l'état du programme.. Elle fournit simplement une valeur, sans la stocker définitivement.

Dans un programme :

1
"bon" * 2

Ce programme n'a aucun effet, ni en mémoire, ni à l'affichage. Sa ligne est bien simplement une expression.

Dans la console interactive :

>>> "bon" * 2 'bonbon'

Attention, l'affichage obtenu est juste dû au fait qu'on soit dans la console : puisqu'on ne fait rien du résultat de l'expression, il est redirigé vers la sortie console. La même ligne n'aurait aucun effet dans un programme.

Instruction

Une instruction modifie l'état du programme (soit sa mémoire, soit en modifiant l'IHM).

  • L'instruction la plus fondamentale est l'affectation : on crée une variable en mémoire.
  • Dans un programme :

    1
    a = 5

    Dans la console :

  • L'utilisation d'une méthode du module Turtle est bien une instruction : on modifie l'affichage à l'écran et donc l'état de l'interface graphique.
Exemples
>>> "bon" * 2 # EXPRESSION (comme elle est seule et qu'on est dans la console, on obtient son affichage) 'bonbon' >>> a = "bon" * 2 # INSTRUCTION : AFFECTATION >>> print("bon" * 2) # INSTRUCTION (on agit sur l'IHM Console) bonbon

Notez bien que la console Python affiche le résultat d'une expression non redirigée ailleurs.

01 ✔° Dans Thonny, sélectionner le menu AFFICHAGE-VIEW et y prendre l'option VARIABLES. Vous devriez voir un panneau s'afficher sur la droite.

02° Taper les instructions suivantes dans la console de Thonny.

Questions

  • Attribuer le mot qui semble le plus pertinent à chacune des 3 lignes : affectation ou simple évaluation.
  • Pourquoi la console affiche-t-elle quelque chose uniquement lors de a + 2 ?
  • Voyez-vous apparaître quelque chose dans le panneau VARIABLES situé à droite lors de a = 5 et b = a + 4 ?
  • Pourquoi a + 2 n'a pas modifié a ?
>>> a = 5 >>> a + 2 7 >>> b = a + 4

...CORRECTION...

  • Attribuer le mot qui semble le plus pertinent à chacune des 3 lignes : affectation ou simple évaluation.
  • >>> a = 5 AFFECTATION >>> a + 2 SIMPLE EVALUATION 7 >>> b = a + 4 AFFECTATION
  • Pourquoi la console affiche-t-elle quelque chose uniquement lors de a + 2 ?
  • On demande simplement d'évaluer le résultat. La console Python est configuré pour afficher le résultat d'une évaluation si on ne rien du résultat évalué.

  • Voyez-vous apparaître quelque chose dans le panneau VARIABLES situé à droite lors de a = 5 et b = a + 4 ?
  • On voit apparaître deux variables nommées a et b. Elles référencent les résultats qu'on a calculé du côté droite.

  • Pourquoi a + 2 n'a pas modifié a ?
  • Il n'y a pas d'affectation. Uniquement une évaluation.

03° Sans taper les lignes de commandes, estimer les deux résultats qui seraient affichés (ou pas !) à l'écran. Soyez vigilant !

Vérifier et demandez conseil si le résultat vous surprend.

>>> a = 5 >>> b = 10 >>> a = 2 >>> a + 2*b ... >>> c = (a+2) * b ... >>> c*2 ...

...CORRECTION...

De façon séquentielle, on obtient les choses suivantes :

  1. Une variable nommée a fait référence à 5.
  2. Une variable nommée b fait référence à 10.
  3. Une variable nommée a fait référence à 2, on écrase donc l'ancienne référence.
  4. On évalue l'expression a + 2*b qui donne donc 2 + 2*10, soit 22. Comme on ne fait rien de cette évaluation, la console affiche le résultat.
  5. On évalue l'expression (a+2) * b qui donne donc (2+2) * 10, soit 40. On affecte ce résultat à une variable c. La console ne va donc rien afficher puisqu'on fait quelque chose de notre évaluation précédente.
  6. On évalue l'expression c *2 qui donne donc 40 * 2, soit 80. Comme on ne fait rien de cette évaluation, la console affiche le résultat.

04° Que vaut a après avoir tout exécuté ? Comment se nomment ces affectations où on modifie le contenu d'une variable en fonction de son ancien contenu ?

>>> a = 20 >>> a = a + 1 >>> a ... >>> a = a + 1 >>> a ... >>> a = a + 2 >>> a ...

...CORRECTION...

>>> a = 20 >>> a = a + 1 >>> a 21 >>> a = a + 1 >>> a 22 >>> a = a + 2 >>> a 24

On part de 20 et on incrémente deux fois de 1 et une fois de 2. On atteint donc 24.

Ce sont des INCREMENTATIONS.

05° Expliquer, en la justifiant, la valeur finale qui sera attribuée à b sur la dernière ligne.

>>> b = 10 >>> b = b + 1 >>> b = b * 2 >>> b ...

...CORRECTION...

>>> b = 10 # b référence 10 >>> b = b + 1 # incrémentation de 1, donc 11 >>> b = b * 2 # multiplication par 2, donc 22 >>> b # Simple évaluation dans la console, donc provoque un affichage 22

06° Expliquer les deux affichages obtenus :

>>> a = 5 >>> type(a) ... >>> a*2 ... >>> b = str(a) >>> type(b) ... >>> b*2 ...

...CORRECTION...

1e cas : a désigne 5, un integer.

L'opérateur * appliqué sur a revient donc à faire une multiplication et donne bien 10.

b désigne elle la version string de 5 : "5".

L'opérateur * appliqué sur b revient donc à faire une répétition : b * 2 est alors évaluée à "55"

07° Expliquer la valeur finale qui sera attribuée à b sur la dernière ligne sur les deux exemples ci-dessous.

Cas 1

>>> a = "10" >>> b = 2 * a >>> b ...

Cas 2

>>> a = 10 >>> b = a >>> b = b + 1 >>> b ...

...CORRECTION...

Cas 1

>>> a = "10" # a référence un STRING ! >>> b = 2 * a # b référence donc "1010" >>> b # simple évaluation, donc affichage '1010'

Cas 2

>>> a = 10 # a référence un integer >>> b = a # b référence donc 10 >>> b = b + 1 # Incrémentation, on passe à 11 >>> b # Simple évaluation 11
2.4 Variable : pas de retroaction

Si une variable est définie à un certain moment à partir du contenu d'une autre variable, la modification ultérieure de cette variable n'aura aucune conséquence.

>>> a = 10 >>> b = a # on définit donc b à 10 ici >>> a = 20 >>> b # avoir modifié a ne remodifie pas b ! 10

08° Expliquer, en la justifiant, la valeur finale qui sera attribuée à b sur la dernière ligne.

>>> a = 10 >>> b = 2 * a >>> a = 0 >>> b ...

...CORRECTION...

>>> a = 10 # a référence 10 >>> b = 2 * a # b référence 20 >>> a = 0 # a référence maintenant 0 >>> b # simple évaluation 20

Le point important est bien évidemment qu'on n'a pas recalculé b sous pretexte que a a été modifiée après l'affectation de b.

✎ 09° Sans taper les lignes de commandes, tenter de trouver la valeur finale qui sera attribuée à b sur la dernière ligne. Justifier votre avis. Vérifier.

>>> a = "Pa" >>> b = "n " >>> b = a + b >>> b = b * 3 >>> a = "Ro" >>> b ...

...CORRECTION...

>>> a = "Pa" >>> b = "n " >>> b = a + b # concaténation "Pan" dans b >>> b = b * 3 # Répétition "PanPanPan" dans b >>> a = "Ro" # Modification de a >>> b # Simple affectation 'PanPanPan'

Encore une fois, pas de retro-action.

2.5 Variable : permutation de deux contenus

Une chose très courante en informatique : la permutation de deux contenus, c'est à dire l'"inversion".

Principe de la permutation

Puisqu'un humain a deux mains, il est facile pour lui de permuter deux objets de place.

L'ordinateur ne peut faire qu'une chose à la fois.

Il aura donc besoin d'une zone de stockage temporaire.

Pour permeture les contenus de argentGauche et argentDroite, il faut une troisième variable videPoche temporaire.

Cela se fait en 3 étapes :

  1. videPoche = argentDroite
  2. --> on copie le contenu de droite dans videPoche.

  3. argentDroite = argentGauche
  4. --> on écrase la valeur à droite en y plaçant la valeur à gauche. Sans videPoche, l'ancienne valeur de argentDroite aurait disparue.

  5. argentGauche = videPoche
  6. --> on écrase la valeur à gauche en y plaçant le contenu de la variable temporaire qui contient la valeur initialement à droite

Inversion en trois étapes
CLIQUER SUR L'IMAGE pour ANIMER ou STOPPER
  1. videPoche = argentDroite
  2. argentDroite = argentGauche
  3. argentGauche = videPoche
Méthode en 3 lignes avec Python
>>> g = 7 >>> d = 55 >>> temp = d >>> d = g >>> g = temp >>> g 55 >>> d 7
Méthode en une ligne, un facilitateur avec Python

Le but de la NSI est de comprendre comment les choses fonctionnent, pas d'appliquer des recettes magiques. Dans un premier temps, on vous demandera donc d'appliquer plutôt la méthode en 3 lignes. Mais Python permet de permuter en une ligne :

g, d = d, g

>>> g = 7 >>> d = 55 >>> g, d = d, g >>> g 55 >>> d 7

Dans les premiers mois de NSI, vous aurez d'abord à utiliser la méthode en 3 lignes. Une fois que cela sera acquis, vous aurez le droit à la permutation en une ligne (et nous verrons comment cela fonctionne).

10° Réaliser la permutation des variables x et y en utilisant une variable temporaire intermédiaire.

>>> x = "Alice" >>> y = "Bob"

...CORRECTION...

>>> x = "Alice" >>> y = "Bob" >>> temp = x >>> x = y >>> y = temp >>> x 'Bob' >>> y 'Alice'

11° Réaliser la permutation des variables x et y en une seule ligne.

>>> x = "Alice" >>> y = "Bob"

...CORRECTION...

>>> x = "Alice" >>> y = "Bob" >>> x,y = y,x >>> x 'Bob' >>> y 'Alice'
2.6 Variable ou CONSTANTE ?

Définition : variable

Une variable est un symbole qui associe un nom et une valeur.

L'association est variable au cours du temps.

Exemple

Sur l'exemple, la variable a commence par référencer 10 puis 20 un peu plus loin dans le programme.

1 . . 28
a = 10 ... ... a = 20
Définition : CONSTANTE

Une CONSTANTE est un symbole qui associe DEFINITEMENT un nom et une valeur.

Par convention, les noms des constantes sont constitués uniquement de majuscules.

Bien entendu, on peut changer la valeur entre chaque lancement de programme, mais on ne doit pas la modifier en utilisant une deuxième affectation ailleurs dans le programme.

Exemple

1 . .
NBR_CASES = 10 ... ...

on ne doit jamais modifier le contenu de NBR_CASES à moins de relancer le programme avec une autre valeur.

En Python

Il n'y a aucun moyen de créer de véritables constantes en Python. Un nom de variable en majuscule informe le développeur qu'on ne veut pas modifier cette variable après la première affectation.

2.7 Variable : affectations multiples

Un autre facilitateur que nous éviterons d'utiliser mais que vous pourriez rencontrer :

>>> a = b = c = 10 >>> a 10 >>> b 10 >>> c 10

3 - Variable : portée des variables

Cette partie est plutôt destinée à être commentée par le prof au tableau plutôt que d'être réalisée en total autonomie.

Vous allez voir maintenant pourquoi il est inutile de donner des noms différents aux paramètres de plusieurs fonctions. Sur l'exemple ci-dessous, Python ne fera aucune confusion entre les trois versions du paramètre feutre :

1 2 3
def deplacer(feutre, x, y) : def trois(feutre, distance, angle) : def triangle(feutre, cote) :

Heureusement car sinon, il faudrait à chaque fois donner un nom un peu différent comme sur cet exemple :

1 2 3
def deplacer(feutre, x, y) : def trois(ftr, distance, angle) : def triangle(f, cote) :

Vous imaginez si on devait se souvenir des noms de toutes les variables et paramètres utilisés dans les 300 000 lignes de votre programme... Il n'y aurait qu'un seul informaticien au monde et il ressemblerait à l'Oeil Qui Voit Tout et travaillerait depuis le Mordor...

Sauron voit tout
L'Oeil de Sauron : Gif provenant de https://gifer.com
Tour de Sauron
Bienvenue au Mordor ! Image CC Public Domain Certification
3.1 Variables locales

3.1.1 Variable locale

On appelle variable locale une variable temporaire qui est définie dans une fonction.

  1. Avant l'appel, cette variable n'existe pas.
  2. Pendant l'appel, elle existe le temps de cet appel précis.
  3. Après le return, la variable est détruite définitivement.

Conséquences :

  • Depuis sa propre fonction : la variable est accessible en lecture et modification.
  • Depuis le programme principal : elle est inconnue.
  • Depuis une autre fonction : elle est inconnue.
  • Depuis un autre appel de la même fonction : la variable du nouvel appel porte le même nom, mais il s'agit bien d'une autre variable.
portée des variables locales
Qui peut utiliser la variable locale x ?
3.1.2 Exemples d'illustration
1 2 3 4 5 6 7 8 9
def f(valeur): a = valeur * 2 print("Depuis la fonction :") print(a) # on tente d'afficher a... print(a) # on tente d'afficher a... f(10) print(a) # on tente d'afficher a... f(30)

Ligne 6 (avant l'appel)  lire a depuis le programme principal ne fonctionne pas. On provoquerait une erreur puisque a n'existe pas.

Ligne 8 (après l'appel f(10)) : lire a depuis le programme principal provoque une erreur puisque a n'existe plus.

print(a) # on affiche la variable locale NameError: name 'a' is not defined

Ligne 4 (pendant l'un des appels) : lire a depuis la fonction fonctionnerait (mais il faut supprimer ou commenter les lignes 6 et 8 (avec #) pour les empêcher de s'exécuter.

Depuis la fonction : 20 Depuis la fonction : 60
Distinction Locale Globale
CLIQUER SUR L'IMAGE pour ANIMER ou STOPPER
portée des variables locales
3.2 Variables globales

3.2.1 Variable globale

On appelle variable globale une variable permanente qui est définie dans le corps du programme, hors de toute fonction.

Permanente, elle existe jusqu'à la fin du programme.

  • Depuis le programme principal : elle est accessible en lecture et modification
  • Depuis les fonctions : elle est accessible en lecture uniquement : une nouvelle affectation avec ce nom crée simplement une variable locale de même nom.

Seule possibilité pour qu'elle disparaisse : la supprimer volontairement avec le mot-clé del. Exemple : del a permet de supprimer la variable a.

portée des variables globales
Qui peut utiliser la variable globale x ?
3.2.2 Exemple : lecture possible

En ligne 2, on lit directement valeur globale depuis la fonction.

1 2 3 4 5 6 7 8 9
def f(): a = valeur * 2 print("Depuis la fonction :") print(a) # on affiche la variable locale valeur = 10 f() valeur = 30 f()
Depuis la fonction : 20 Depuis la fonction : 60
Distinction Lecture globale possible
CLIQUER SUR L'IMAGE pour ANIMER ou STOPPER
3.2.3 Exemple : modification impossible

Voici un autre programme montrant que la fonction ne parvient pas à modifier la variable globale : ligne 2, on crée en réalité une variable locale qui disparaitra après l'appel.

Il y aura donc temporairement deux variables portant le même nom. Depuis la fonction, on lira juste la variable locale, et on ne pourra plus voir la variable globale.

1 2 3 4 5 6 7 8 9 10 11
def f(): valeur = 100 # on tente de modifier valeur globale... print("Pendant l'appel à f() :") print(valeur) # on tente d'afficher valeur... valeur = 2 print("Avant l'appel à f() :") print(valeur) # on tente d'afficher valeur... f() print("Après l'appel à f() :") print(valeur) # on tente d'afficher valeur...
Avant l'appel à f() : 2 Pendant l'appel à f() : 100 Après l'appel à f() : 2
Modification globale impossible depuis une fonction
CLIQUER SUR L'IMAGE pour ANIMER ou STOPPER
portée des variables globales
Affectation en local avec le même nom qu'en global : pas de modification au global

Il faut bien comprendre que faire une affectation en local en utilisant le même nom qu'une variable globale ne fait que créer temporairement une variable locale qui va cacher la variable globale.

Une fois sortie de la fonction, la variable globale n'aura pas bougé.

3.3 Savoir différencier locales et globales

3.3.1 Exemple
1 2 3 4 5 6 7 8 9
def modification(a): print(a) a = 5 print(a) return a * 10 a = 10 b = modification(a) print(a)
  • Locales : a
  • Globales : modification(), a aussi, b

En lignes 1 à 5, a est locale à la fonction.

En lignes 7, 8 et 9, a est globale au programme.

3.3.2 Comment ne pas s'embrouiller ?

On rajoute mentalement des suffixes aux variables qui portent le même nom !

Même programme mais en rajoutant des suffixes dans sa tête :

  1. a_mod pour les a qui appaissent dans la fonction modification().
  2. a_glo pour les a qui appaissent dans le programme principal.
1 2 3 4 5 6 7 8 9
def modification(a_mod): print(a_mod) a_mod = 5 print(a_mod) return a_mod * 10 a_glo = 10 b = modification(a_glo) print(a_glo)

En lignes 1 à 5, la variable a_mod est une variable locale à la fonction.

En lignes 7, 8 et 9, la variable a_glo est une variable globale au programme. Il ne s'agit pas de la même que celle des lignes 1 et 5.

Par contre, au début de l'appel puisqu'on envoie a_glo dans a_loc, ce sont temporairement des alias qui pointent vers le même contenu en mémoire. Jusqu'à la ligne 3, où on réalise une affectation : on crée alors une vraie variable locale dissociée.

Visuel de la situation

    Distinction Locale Globale
    CLIQUER SUR L'IMAGE pour ANIMER ou STOPPER
3.4 Variables : Espace des noms

3.4.1 Les espaces des noms

Lors d'une affectation, Python crée une association entre le nom de la variable et un contenu en mémoire.

L'ensemble de ces associations se nomme l'espace des noms.

Il existe en réalité plusieurs espaces des noms.

  • L'espace des noms global et permanent du programme : il existe pendant tout le déroulement du programme.
  • Chaque appel de fonction crée un espace des noms local temporaire qui est détruit après l'appel.

On peut voir visuellement ces zones dans Python Tutor. La zone grise est l'espace des noms actuellement utilisé par Python.

3.4.2 Utilisation par Python

Lorsque Python doit évaluer une variable dans une fonction :

  1. Il commence par chercher dans l'espace local.
  2. Si il ne trouve pas, il cherche ensuite dans l'espace global.
  3. S'il ne trouve toujours pas de variable portant ce nom, il déclenche une exception NameError.

Traduit en Python, cela donnerait quelque chose comme ceci :

1 2 3 4 5 6 7 8 9 10 11 12 13
def evaluer_variable(nom): espace_local = locals() # espace local actuel sous forme d'un dico espace_global = globals() # idem mais pour l'espace global if nom in espace_local: # si le nom est bien une clé de l'espace local return espace_local[nom] # on renvoie son contenu mémoire elif nom in espace_global: # sinon si le nom est une clé de l'espace global return espace_global[nom] # on renvoie son contenu mémoire else: # sinon, raise NameError # on lève l'exception NameError
3.5 Hors programme : fonctions natives globals() et locals()

3.5.1 Fonction native globals()

Cette fonction renvoie un dictionnaire qui contient plusieurs clés.

  • Les noms des variables globales apparaissent comme clés de ce dictionnaire.
  • Les valeurs sont les contenus associés aux variables.
3.5.2 Fonction native locals()

Cette fonction renvoie un dictionnaire qui contient plusieurs clés.

  • Les noms des variables l'espace local actuel apparaissent comme clés de ce dictionnaire.
  • Les valeurs sont les contenus associés à ces variables.
3.5.3 Exemple
1 2 3 4 5 6 7 8 9 10 11 12 13
def f(x): y = b * x print("Le dictionnaire de l'espace des noms local de f() :") print(locals()) return y a = 10 b = [10, 100, 1000] c = f(2) print(" ") print("Le dictionnaire de l'espace des noms global :") print(globals())

Imaginons qu'on nomme ce programme portee.py :

>>> %Run portee.py Le dictionnaire de l'espace des noms local de f() : { 'x': 2, 'y': [10, 100, 1000, 10, 100, 1000] } Le dictionnaire de l'espace des noms global : { '__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f0bf3e6fcf8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'portee.py', 'f': <function f at 0x7f0bf3159c80>, 'a': 10, 'b': [10, 100, 1000], 'c': [10, 100, 1000, 10, 100, 1000] } >>> a 10 >>> globals()['a'] 10 >>> locals()['y'] KeyError: 'y'

12° Sans lancer le programme ci-dessous, répondre aux questions suivantes en utilisant juste votre compréhension de la notion de variables. Vérifiez ensuite via la console ou via l'onglet Variable de Thonny.

  • L1 : La fonction modification() va-t-elle se mettre en mémoire ou automatiquement s'exécuter ?
  • L4 : Que contient, à votre avis, la variable a lorsqu'on exécute la ligne 4 ?
  • L5 : Que contient, à votre avis, la variable a après avoir exécuté la ligne 5 ?
1 2 3 4 5
def modification(a): a = a + 5 a = 10 modification(a)

...CORRECTION...

Pour répondre sans confusion aux questions, il suffit de voir le programme de cette façon :

1 2 3 4 5
def modification(a_mod): a_mod = a_mod + 5 a_glo = 10 modification(a_glo)

L1 : La fonction ne s'exécute pas automatique en ligne 1 : il s'agit juste d'une déclaration. On met la fonction modification() dans l'espace global des noms et à partir de maintenant, on pourra y faire appel.

L4 : la variable a_glo du programme principal contient visiblement 10.

L5 : On lance l'appel à la fonction modification() en lui transmettant a_glo qu'on stocke dans un paramètre local qui se nomme a_mod ! Lorsqu'on exécute la ligne 2, on incrémente de 5 la variable a_mod qui passe maintenant à 15.

Ensuite, on sort de la fonction qui répond... rien.

L'espace des noms de la fonction disparait alors, emportant avec lui notre variable a_mod.

La variable a_glo n'a donc pas été modifiée. Elle référence toujours 10.

>>> %Run portee.py >>> a 10
3.6 Fonction randint() du module random

A - Fonction randint()

Le module random contient beaucoup de fonctions permettant de gérer l'aléatoire.

Il existe notamment la fonction randint() qui permet de générer un integer aléatoire entre une valeur de départ incluse et une valeur de fin incluse.

Cette fonction doit recevoir deux entrées : la première est la valeur de départ autorisée, et la deuxième la valeur finale autorisée. Ainsi en fournissant 5 et 8, on génère un nombre aléatoire entre 5 et 8 pouvant valoir 5, 6, 7 ou 8.

Si on veut simuler un d6, un dé à 6 faces, il suffit de taper ceci (notez bien qu'on importe randint() depuis le module, pas tout le module) :

>>> from random import randint >>> randint(1, 6) 4 >>> randint(1, 6) 1 >>> randint(1, 6) 6 >>> randint(1, 6) 2
B - Exemple d'un programme créant des notes au hasard

Ci-dessous, un programme générant 10 notes aléatoires entre 0 et 20 (notez bien qu'ici, nous importons uniquement le module random) :

1 2 3 4 5 6 7
import random # Importation du module notes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # Tableau de dix entiers for i in range(10): # Pour i variant de 0 à 9 notes[i] = random.randint(0, 20) # Case i contient un nbr entre 0 et 20 print(notes) # Affiche lorsque la boucle est finie
>>> %Run portee.py [19, 14, 5, 7, 3, 18, 16, 1, 8, 7] >>> %Run portee.py [4, 7, 13, 13, 11, 16, 4, 7, 9, 12]
C - Remarque importante

Notez bien :

  • qu'avec randint(2, 5), la valeur finale est incluse dans les choix possibles : 2, 3, 4 ou 5.
  • qu'avec range(5), la valeur "finale" 5 n'est pas incluse : nous allons générer progressivement 0, 1, 2, 3, 4 mais PAS 5.

A vous de le savoir, cela a été défini comme cela.

13° Répondre aux questions suivantes liées aux appels de fonctions.

  1. Sur quelle ligne se trouve la déclaration de la fonction lancement() ? Combien d'entrées sont-elles attendues ? (0, 1, 2, 3 ... ?)
  2. Sur quelle ligne se trouve l'apppel de la fonction lancement() ?
  3. Quelle la valeur envoyée à la fonction lancement() lors de cet appel ?
  4. Dans quelle variable la fonction lancement() stocke-t-elle ce qu'on lui a envoyé ?
  5. Donner les lignes suivies par l'interpréteur pendant l'exécution de ce programme.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" minimum = 20 maximum = 100 for n in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n) nombre = 5 lancement(nombre) print("FIN")

...CORRECTION...

  1. Sur quelle ligne se trouve la déclaration de la fonction lancement() ?
  2. Ligne 4, une seule entrée à fournir un jour.

  3. Sur quelle ligne se trouve l'apppel de la fonction lancement() ?
  4. Ligne 17.

  5. Quelle la valeur envoyée à la fonction lancement() lors de cet appel ?
  6. On voit ligne 17 qu'on envoie nombre, donc 5.

  7. Dans quelle variable la fonction lancement() stocke-t-elle ce qu'on lui a envoyé ?
  8. En regardant ligne 4, on voit qu'elle stocke son entrée dans nbr.

  9. Donner les lignes suivies par l'interpréteur pendant l'exécution de ce programme.
  10. L1 (importation du module, pas de la fonction directement)

    L4 (déclaration d'une fonction)

    L16

    L17 (appel de fonction) - L4 (réception de l'entrée 5)

    L7 - L8

    L9 (avec n=0)-L10-L11 (nous avons un range(6)

    L9 (avec n=1)-L10-L11

    L9 (avec n=2)-L10-L11

    L9 (avec n=3)-L10-L11

    L9 (avec n=4)-L10-L11

    L9 (avec n=5)-L10-L11

    L12-L13

    L17 (retour au point d'appel) - L18

14° Notez (sans justification particulière) pour chacune des variables surlignées dans le programme s'il s'agit d'une variable locale ou d'une variable globale. Dire ensuite ce que contient la mémoire à la fin du programme et qui restera accessible depuis la console : quelle(s) variable(s), quelle(s) fonction(s), quelle(s) module(s).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" minimum = 20 maximum = 100 for n in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n) nombre = 5 lancement(nombre) print("FIN")

...CORRECTION...

1 2 3 4 (locale) 5 6 7(locale) 8(locale) 9(locale) 10(locale) 11 12 13 14 15 16(globale) 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" minimum = 20 maximum = 100 for n in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n) nombre = 5 lancement(nombre) print("FIN")

Après être sorti de la fonction, son espace des noms est supprimé.

Il ne restera donc en mémoire que :

  • Le module random
  • La fonction lancement
  • La variable nombre.

15° On a modifié l'endroit où on déclare les variables minimum et maximum.

Répondre aux questions suivantes :

  1. Dire si les variables surlignées sont locales ou globales.
  2. Expliquer ce que va faire Python en tombant sur la ligne 8 et indiquer notamment s'il déclare une erreur ou pas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" for n in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n) minimum = 20 maximum = 100 nombre = 5 lancement(nombre) print("FIN")

...CORRECTION...

1 2 3 4 5 6 7 8(globales) 9 10 11 12 13 14(globale) 15(globale) 16 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" for n in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n) minimum = 20 maximum = 100 nombre = 5 lancement(nombre) print("FIN")

Puisqu'il n'y a pas de déclaration de variables portant ce nom dans la fonction, il s'agit de variables globales.

Lorsqu'il tombe sur la ligne 8, l'interpréteur fouille d'abord dans l'espace des noms local. Il n'y trouve aucune variable portant ces noms. Il va alors fouiller dans l'espace des noms global et trouvera les deux variables globales.

Puisqu'une fonction peut LIRE les variables globales, il n'y aura aucune erreur. Le programme fonctionnera normalement et tirera des nombres aléatoires entre 20 et 100.

16° On modifie le programme une dernière fois en remplaçant, sur la ligne 16, le nom de la variable globale nombre par n comme la variable de boucle de la ligne 7.

  1. Cela va-t-il poser problème ?
  2. Quel est le contenu de n à la fin du programme ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" for n in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n) minimum = 20 maximum = 100 n = 5 lancement(n) print("FIN")

...CORRECTION...

Aucun problème puisqu'il ne s'agit pas de la même variable !

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import random def lancement(nbr): """Affiche nbr résultats aléatoires compris entre minimum et maximum""" for n_lan in range(nbr + 1): resultat = random.randint(minimum, maximum) print(resultat) print("A la fin de la boucle, n vaut") print(n_lan) minimum = 20 maximum = 100 n_glo = 5 lancement(n_glo) print("FIN")

Dès que la fonction a répondu, n_lan disparaît. Il n'y a donc aucune ambiguïté lorsqu'on demande à lire n. Il s'agit nécessairement de n_glo qui n'a jamais été modifiée et contient toujours son 5 du début.

4 - FAQ

On peut détruire une variable ?

Oui, on peut libérer la place mémoire attribuée à une variable. Pour cela, il faut utiliser le mot-clé del.

Exemple :

>>> a = 5 >>> a 5 >>> del a >>> a NameError: name 'a' is not defined

J'ai vu une notation bizarre : a += 1

Effectivement, on peut également utiliser une autre notation.

1 2
a = 10 a += 1

Cela donne ici le même résultat que ceci :

1 2
a = 10 a = a + 1

Attention, les deux façons de faire sont équivalentes ici, mais pas toujours. Evitez ces notations pour l'instant. De toutes manières, elles ne seront pas utilisées dans les sujets de NSI. Gardez la méthode n°2. C'est plus long mais c'est moins compliqué à comprendre de toutes manières.

L'activité suivante : comment organiser un programme.

Avec quelques exemples pratiques dans différents domaines.

Activité publiée le 28 08 2019
Dernière modification : 13 07 2023
Auteur : ows. h.