Interface, variables, opérations : cours

\(\newcommand{\ds}{\displaystyle}\) \(\newcommand{\Frac}{\ds\frac}\) \(\renewcommand{\r}{\mathbb{ R}}\) \(\newcommand{\C}{\mathbb{ C}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\z}{\mathbb{ Z}}\) \(\newcommand{\Q}{\mathbb{ Q}}\) \(\newcommand{\N}{\mathbb{ N}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\ol}{\overline}\) \(\newcommand{\abs}[1]{\left| \,{#1} \right|}\) \(\newcommand{\pv}{\;;\;}\) \(\newcommand{\ens}[1]{\left\{ {#1} \right\}}\) \(\newcommand{\mens}[1]{\setminus\left\{ {#1} \right\}}\) \(\newcommand{\Par}[1]{\left({#1}\right)}\) \(\newcommand{\pe}[1]{\left\lfloor {#1} \right\rfloor}\) \(\newcommand{\trans}[1]{\,^t\!{#1}}\)

Interface, variables, opérations : cours

Cours

Le processus de programmation en Python

Le cycle de programmation

Soit à produire un programme écrit en langage Python et qui résout un problème, par exemple :

PROBLÈME : calculer et afficher la date du prochain vendredi 13.

On considère un programmeur qui a les compétences suffisantes pour écrire un tel programme. Le programmeur ouvre un environnement de programmation. Voici les étapes par lesquelles il va passer :

  • Étape 1 : édition du code-source

    Le programmeur ouvre un logiciel plus ou moins sophistiqué permettant de saisir (au clavier) le code-source dans le langage de programmation Python et censé résoudre le problème posé et il écrit ce code-source, cf. la première image ci-dessous.

  • Étape 2 : exécution du code-source

    Le programmeur exécute le code qu’il a écrit à l’étape 1 pour voir si ce code réalise bien ce pour quoi il a été écrit, ici trouver le prochain vendredi 13, cf. la deuxième image ci-dessous. Si ce n’est pas le cas, il revient à l’étape 1 et modifie le code-source.

../../../_images/editionCodePython_VSCode.png

Étape 1 : code Python saisi dans VSCode

../../../_images/executionCodePython_VSCode.png

Étape 2 : exécution du code précédent. On lit la réponse dans la console en bas

Même pour un nouveau-venu à la programmation, le schéma en deux étapes ci-dessus reste valide.

L’étape 1 est en général la plus longue et la durée et la qualité de la réalisation de cette étape vont dépendre des connaissances plus ou moins approfondies du programmeur.

Programme du vendredi 13

Concernant le problème du prochain vendredi 13, le programmeur pourrait écrire dans un code-source tel que celui-ci :

vendredi13.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from datetime import date

def prochain13(x):
    m = x.month
    d = x.day
    y = x.year
    if d < 13:
        return date(y, m, 13)
    else:
        if m < 12:
            return date(y, m + 1, 13)
        else:
            return date(y + 1, 1, 13)

x = date.today()

while True:
    x = prochain13(x)
    if x.weekday() == 4:
        print(f'vendredi 13/{x.month}/{x.year}')
        break

Si vous exécutez le code vendredi13.py en 2021, selon la période de l’année, il affichera

vendredi 13/8/2021

ou sinon

vendredi 13/5/2022

Le cycle édition-exécution

Selon que le résultat de l’étape 2 est satisfaisant ou pas, le programmeur retourne à l’étape 1 pour modifier le code-source et ainsi de suite : c’est le cycle dit édition-exécution.

Suivant les programmes, ce cycle peut s’étaler entre quelques secondes (pour les petits programmes) et plusieurs mois pour de programmes complexes et volumineux, faits en équipe.

Pouvoir utiliser un interpréteur

Pour coder en Python, il faut disposer d’un logiciel appelé un interpréteur Python qui puisse exécuter du code écrit en Python. Pour disposer d’un interpréteur, il y a deux situations :

  • l’interpréteur est distant, accessible via Internet depuis un site web
  • l’interpréteur est local, installé sur l’ordinateur avec lequel vous travaillez

Dans le cadre d’un auto-apprentissage de Python, la solution de l’interpréteur local suppose, la plupart du temps, que c’est vous qui vous chargez de l’installation de Python et aussi … des difficultés qu’elle peut occasionner.

L’interpréteur distant a tous les avantages (et les inconvénients) d’une utilisation via une connexion Internet. Voici quelques avantages :

  • vous n’avez rien à installer sur votre machine,
  • l’interpréteur fonctionnera quel que soit votre système d’exploitation,
  • vous pourrez coder depuis n’importe quel ordinateur connecté à Internet,
  • votre interpréteur sera à jour en permanence (avec des nuances),
  • votre code est sauvegardé à distance (avec des nuances),
  • vous pouvez facilement partager votre code avec d’autres personnes (avec des nuances).

Pour apprendre ou enseigner Python, le choix de l’interpréteur distant est à considérer.

Environnement de programmation

Un environnement de programmation pour Python désignera un outil logiciel permettant à la fois d’éditer du code Python et de l’exécuter. Un environnement de programmation peut être être distant ou être installé localement sur votre machine. Par exemple,

  • les éditeurs IDLE (cf. la première image ci-dessous) ou VScode sont des éditeurs locaux ;
  • des applications web comme Google colab (cf. la deuxième image ci-dessous) ou tutorialspoint proposent un environnement de programmation distant.
../../../_images/executionCodePython.png

Un éditeur local : l’éditeur intégré par défaut IDLE

../../../_images/jupyter-editeur-en-ligne_colab.png

Un éditeur distant sur Google Colab

Tout environnement de programmation contient 2 zones bien distinctes (cf. les images ci-après):

  • une zone d’édition de code
  • une zone de sortie

La zone d’édition est la zone de l’éditeur où l’utilisateur écrit son code Python. La zone de sortie est la zone de l’IDE où apparaissent les affichages générés par l’exécution du code de la zone éditeur.

Voici des images de quelques éditeurs intégrés montrant les deux zones :

../../../_images/idle-presentation-legende.png

Zones d’édition de code et d’exécution de code dans l’éditeur IDLE

../../../_images/jupyter-editeur-en-ligne_colab_legende.png

Cellules d’édition de code et d’exécution de code dans l’éditeur distant JupyterLab

En pratique,

  • le programmeur tape son code dans la zone d’édition
  • il appuie sur une touche du clavier ou clique sur un bouton ou dans un menu pour exécuter son code
  • il lit le résultat de l’exécution dans la zone de sortie.

Quelques environnements de programmation

Voici quelques environnements de programmation en Python gratuits, voire open-source :

  • Jupyter Notebook et JupyterLab : l’utilisateur écrit en Python dans des cellules de code au sein d’une page web habituelle, contenant du texte, des images, de la vidéo. Cet environnement est utilisé dans les sciences des données et l’IA (cf. les compétitions Kaggle) et peut-être aussi dans l’éducation. JupyterLab est une évolution des feuilles Jupyter Notebook. L’environnement Google Colab utilise JupyterLab. Jupyter Notebook peut s’installer sur sa propre machine, soit via pip soit en utilisant la suite Anaconda.
  • VSCode : l’éditeur multi-langage et open-source proposé par Microsoft. Selon plusieurs enquêtes, il serait un des éditeurs les plus utilisés, en particulier dans le monde professionnel. Le créateur du langage Python et le créateur de l’extension Python de VSCode travaillent pour Microsoft.
  • IDLE : il est disponible par défaut quand on utilise la distribution « officielle » téléchargée depuis python.org et donc ne nécessite aucune installation (sauf sous Linux). C’est probablement un des éditeurs les plus simples mais son interface est limitée et, surtout, assez désuète ce qui ne le rend pas très populaire.
  • Spyder : environnement de programmation en Python destiné aux scientifiques, ingénieurs, analystes de données. Serait utilisé dans l’enseignement.

Aucun environnement de programmation n’est simple à prendre en main quand on en a jamais utilisé et si on débute, il est préférable de choisir un environnement aussi simple que possible (IDLE, Jupyter Notebook) sinon, l’expérience de programmation est altérée. Il y a un certain flottement dans l’usage des termes suivants : éditeur de code, environnement de développement intégré (IDE) et environnement de programmation. Par exemple, VSCode n’est pas considéré comme étant un IDE mais un éditeur.

Installer et lancer Jupyter sous Windows 10 ou 11

L’environnement de travail Jupyter est un module Python et qui s’intalle donc en utilisant le gestionnaire de packages pip livré avec Python. Les étapes d’installation sont les suivantes :

  • ouvrir ce qu’on appelle une « invite de commande » Windows qui est un terminal où on peut entrer des commandes au clavier ; pour cela,

    • ouvrir la zone de recherche disponible dans la barre des tâches de Windows
    • taper cmd dans la barre et valider
    • vous devriez voir apparaître une image du terminal : cliquer dessus pour y accéder.
  • devant le prompt, taper la commande pip install notebook et valider : cela va installer en moins d’une minute l’environnement Jupyter Notebook. Une fois installé, fermer la ligne de commande.

Ensuite, pour lancer Jupyter Notebook, ouvrir à nouveau une invite de commande, taper jupyter notebook et valider. Au bout de quelques secondes (ça peut être plusieurs dizaines de secondes en fait), dans votre navigateur web, va s’ouvrir la page d’acceuil de Jupyter et qui correspond à un de vos répertoires. De là, vous pouvez créer une feuille Jupyter Notebook ou en ouvrir une qui soit disponible en allant à l’emplacement où se trouve la feuille.

Il existe d’autres méthodes d’installation, comme utiliser Anaconda mais qui n’est pas justifiée pour une utilisation basique de Python. On peut aussi utiliser Jupyter Notebook dans VScode.

Feuilles Jupyter Notebook : usage

Les feuilles de travail Jupyter étant des applications Web, elles utilisent le même format, qu’elles soient utilisées en ligne (Cocalc, Google Colab ou autres) ou en local (Windows, Linux, macOs). Les copies d’écran ci-dessous sont anciennes mais sont encore valides en 2024.

Le dashboard

Après avoir lancé Jupyter, votre nagivateur web s’ouvre sur une page d’accueil permettant d’accéder à des répertoires de votre système de fichiers et d’ouvrir des feuilles ipynb : il s’agit du dashboard, c’est le terme employé dans la documentation.

../../../_images/jupyter-dashboard.png

Le dashboard de Jupiter

Sur une installation locale, la page ouverte correspond au répertoire de lancement de Jupyter.

Depuis cette page, on peut naviguer dans une arborescence de répertoires ; on peut aussi créer des répertoires (bouton New), lesquels apparaîtront dans votre système de fichiers si votre installation est locale. On peut aussi les renommer (cocher le répertoire et un bouton apparaît), et attention, les supprimer (donc par mégarde, vous pouvez supprimer un de vos propres répertoires, sans possibilité de récupération dans la corbeille).

Création d’une nouvelle feuille

Pour créer une nouvelle feuille, naviguez depuis le dashboard jusque dans le dossier où vous voulez que se trouve votre feuille de trvail. Puis, cliquer depuis le dashboard sur le bouton New puis choisir le moteur Python 3.

../../../_images/creer_feuille_jupyter.png

Créer une feuille Jupyter

Cela crée dans le répertoire courant affiché par le dashboard, une feuille de travail Jupyter, nommée par défaut Untitled et qui s’ouvre automatiquement. Renommez éventuellement la feuille en cliquant sur son nom en haut à gauche. Si on renomme la feuille en maFeuille, le nom du fichier créé sera maFeuille.ipynb d’extension ipynb (ce qui signifie IPython notebook).

Ouverture d’une feuille déjà existante

Depuis le dashboard, naviguer vers le répertoire où se trouve ladite feuille et cliquer sur le nom de la feuille (d’extension ipynb) ce qui va ouvrir la feuille.

Choix du moteur

En principe, le moteur de votre feuille est Python 3. On peut le vérifier en haut à droite, au niveau de la barre de menus. On peut changer le moteur dans le menu Kernel > Change Kernel

../../../_images/change_kernel_jupyter.png

Créer une feuille Jupyter

Description d’une feuille

Une feuille se présente comme une succession de cellules. Il existe 3 catégories de cellules :

  • cellule d’input (ou d’entrée): votre code Python
  • cellule d’output : sortie mode en mode texte, ou graphique
  • cellule de texte : tout contenu web comme texte, image, vidéo, tableau, math, etc.
../../../_images/cellules_jupyter_annotations.png

Les différentes cellules Jupyter

À la création d’une feuille (quand on clique sur New), il existe une unique cellule et cette cellule est une cellule de code.

Vous écrivez votre code dans les cellules d’input et on lit les éventuels affichages dans les cellules d’output. Les cellules d’input sont précédées de In [] et entre crochets figure le numéro dans l’ordre chronologique de l’édition de la cellule.

En tant qu’utilisateur de Python, vous n’êtes pas fondamentalement concerné par les cellules de texte qui sont créées, en langage Markdown, par le créateur de la feuille. Mais par accident, vous pouvez y être confronté ou même volontairement, si vous voulez modifier ou ajouter du texte, voir plus bas.

Entrer du code et l’exécuter

On entre son code dans une cellule d’input comme dans un éditeur de code Python, avec toutes les possibilités habituelles (sélection, suppression, copier-coller, CTRL+Z, coloration syntaxique automatique, etc). La cellule est extensible en hauteur, on peut taper autant de lignes qu’on veut.

Pour valider le code Python d’une cellule, autrement dit pour exécuter ce code, il y a deux possibilités :

  • le bouton en triangle de la barre d’outils
  • le raccourci clavier MAJ + ENTRÉE.

Si le code est correct, il y a une sortie visible (éventuellement pas de sortie, ça dépend en fait des commandes écrites en entrée) sous la cellule d’entrée, avec éventuellement un message d’erreur concernant le code Python entré.

Il est possible de revenir sur une cellule déjà éditée et de la modifier et de revalider son contenu. La numérotation de la cellule est alors modifiée.

Pour, à la fois, valider une cellule de code et ouvrir une cellule de code en dessous, taper Alt + Enter

Réinitialisations

Au fur et à mesure que la feuille est enrichie de code Python exécuté, la mémoire de ce code est enregistrée par la feuille. Pour diverses raisons, il peut être nécessaire de réinitialiser l’état de la mémoire (de faire une purge). Pour cela, cliquer menu Kernel > Restart et accepter la réinitialisation en cliquant sur le bouton coloré.

On peut vouloir nettoyer les cellules de leur sortie (parfois volumineuses). Pour cela menu

Cell > All Output > Clear

Pour interrompre un code trop long à s’exécuter, deux méthodes :

  • menu Kernel > Interrupt.
  • bouton carré noir de la barre d’outils

Insertion, suppression

Pour insérer une nouvelle cellule de code, menu Insert.

Pour supprimer une cellule, placer le curseur dans la cellule et aller au menu Edit > Delete Cells

Du texte bizarre apparaît

Si par mégarde, vous activez une cellule de texte (en faisant un double clic par exemple), un code bizarre va apparaître (c’est du langage Markdown). Pour remédier à cela, placer le curseur dans la cellule bizarre et TAPER MAJ+ ENTRÉE, comme si c’était une cellule de code vous validiez.

Les explications ci-dessus vous montrent aussi comment modifier du texte dans une cellule de texte.

Divers

Les feuilles sont sauvegardées automatiquement à certains intervalles de temps. On peut anticiper la sauvegarde par le menu File > Save and Checkpoint

On peut modifier le titre d’une feuille en cliquant sur son nom en haut à gauche.

Pour une meilleure lisibilité, on peut cacher les barres de menus et d’outils (menu View).

La complétion syntaxique

Dans une cellule, on tape le code suivant, sans valider :

1
2
laJoliVariableInterminablementLongue=42
print(10 * la

On veut poursuivre d’écrire le code en écrivant juste derrière le 10 * la variable à la ligne au-dessus mais comme elle est très longue, on n’a pas envie de la retaper. Pour nous aider, IPython prend en charge la complétion syntaxique. Si on tape les deux ou trois premières lettres de la variable et qu’on appuie sur la touche TAB, le nom de la variable va apparaître, et il suffira de la sélectionner pour qu’elle soit placée dans le code :

../../../_images/completion_syntaxique_jupyter.png

Complétion syntaxique dans Jupyter

Communication entre cellules

Les cellules ne sont pas étanches entre elles. Toute variable déclarée et validée dans une cellule est placée en mémoire et utilisable par les autres cellules, qu’elles soient avant ou après la cellule ou figure cette variable et y compris si la cellule déclarant cette variable est supprimée ou modifiée. Bien sûr, c’est pratique mais cela peut aussi induire des bug dans la mesure où le code d’une cellule dépend de ce qui a été déclaré avant ou ailleurs.

Exportation de la feuille

Il est possible d’exporter une feuille sous différents formats. Pour cela, aller au menu File > Export

../../../_images/exporter_jupyter.png

Menu d’exportation

On peut exporter dans différents formats dont les formats :

  • ipynb : c’est le format natif des feuilles Jupyter
  • py : fichier Python ne contenant que les cellules d’input de la feuille, les autres cellules étant placées en commentaire du code Python.
  • md : fichier Markdown et format html
  • pdf : le fichier va être créé par Jupyter et il a besoin des programmes latex et pandoc pour générer le pdf (sinon, ça ne marchera pas, surtout si Latex n’est pas installé).

Parcourir la feuille

  • Placer le focus dans une cellule, celle à partir de laquelle on va naviguer dans la feuille.
  • Taper sur la touche Echap
  • Pour descendre page par page, appuyer sur Espace
  • Pour remonter page par page, appuyer sur Maj-Espace

Afficher

Soit le code Python dont le contenu est exactement le suivant :

5 + 5
2 + 2

Lorsqu’on demande à Python d’exécuter ce code, Python calculera \(5 + 5 = 10\) puis calculera \(2 + 2 =4\). Ensuite, selon l’environnement de programmation, le programme n’affichera rien ou n’affichera que le résultat du dernier calcul (ici 4).

Pour avoir la garantie que le résultat d’une opération sera affiché et correctement affiché, il faut le demander explicitement à Python avec une fonction fournie par le langage, la fonction print :

1
2
print(5 + 5)
print(2 + 2)

qui affiche

10
4

print est une fonction standard du langage Python pour signifier qu’elle est fournie nativement par le langage Python et immédiatement disponible pour utilisation. Comme c’est une fonction, pour l’utiliser et ainsi obtenir un affichage, il faut placer une paire de parenthèses après le nom print de la fonction et placer entre les parenthèses l’objet à afficher.

Afficher un message

On peut afficher un « message » avec la fonction print. Dans le code-source, le message est placé entre guillemets :

1
print("--->> Bonjour ! <<---")
2
--->> Bonjour ! <<---

Le message peut être plus ou moins élaboré voire fantaisiste.

Variables

Voici un code utilisant une variable, appelée toto :

1
2
toto = 42
print(toto + 10)
3
52
  • Ligne 1 : toto désigne une variable qui référence 42. La variable toto est comme une étiquette qui permet d’accéder à l’entier 42 écrit quelque part en mémoire. L’entier 42 est ce qu’on appelle un objet au sens d’une entité présente dans la mémoire de l’ordinateur au moment où Python examine l’instruction toto = 42.

  • Ligne 2 :

    • d’abord Python regarde s’il dispose d’une variable toto référencée en mémoire (c’est le cas, cf. ligne 1) puis il récupère le contenu de cet emplacement-mémoire et effectue le calcul demandé.
    • toto + 10 est une expression et qui a une valeur (ici 52).
    • print permet d’afficher la valeur de l’expression.

Un nom de variable est sensible à la casse (lettre en majuscule ou minuscule) :

1
2
3
4
year = 2000
Year = 3000
print(year)
print(Year)
5
6
2000
3000

Vocabulaire

  • L’instruction toto = 42 est une affectation : on affecte 42 à la variable toto.
  • Quand une variable est définie pour la première fois, la première valeur qu’elle reçoit lorsqu’elle est définie s’appelle l”initialisation. Donc, ci-dessus, toto est initialisée à 42.

En Python, une variable est définie essentiellement par affectation.

La notion de variable est fondamentale en programmation et est le premier maillon vers l’abstraction. Il est capital d’écrire du code où les données sont placées dans des variables.

Post-it

Un document qui explique très bien le modèle mental de la variable en Python est ICI : une variable Python un post-it que l’on peut placer et déplacer sur des objets.

Voir aussi ce message de Ben Finney ainsi que Facts and myths about Python names and values et regarder la vidéo associée.

Notion d’expression

Soit le code suivant :

1
2
3
4
5
d = 4
u = 2
x = 10 * d + u

print(10 * x + 1)
6
421

On y définit des variables, par exemple d ou u, et en combinant ces variables avec des constantes (comme 10) et des opérateurs comme * et +, on obtient des « écritures » qui s’appellent des expressions, comme 10 * d + u (ligne 3).

En combinant des expressions à nouveau avec des opérateurs et des constantes, on obtient de nouvelles expressions, comme ci-dessus 10 * x + 1 (ligne 5).

Par définition, une expression a toujours une valeur. Par exemple la valeur de l’expression 10 * x + 1 est l’entier 421. En revanche, l’écriture d = 4 (ligne 1) n’a pas de valeur et n’est pas une expression.

Pour afficher une expression E, on utilise l’instruction print(E) et qui affiche dans une sortie sous forme textuelle la valeur de cette expression.

Syntaxe basique des noms de variables

Voici un programme utilisant des noms valides de variables :

1
2
3
4
tokyo = 2020
tokyo2020 = 32
TOKYO = 2020
tokyoTokio = 32

La plupart du temps, un nom de variable est un mot formé de caractères alphabétiques, (majuscules ou minuscules) ou de chiffres. Il ne peut y avoir aucun élément de ponctuation ni d’espace dans un nom de variable, sinon, la plupart du temps, vous aurez une erreur de type syntaxError :

1
chou-fleur = 42
2
SyntaxError: can't assign to operator

Par ailleurs, une variable ne peut commencer par un chiffre :

1
2020Tokyo = 32
2
SyntaxError: invalid syntax

Les noms de variables sont sensibles à la casse :

1
2
tokyo = 2020
print(Tokyo)
  • Ligne 2 : les variables Tokyo et tokyo sont différentes. Le 2e nom n’a pas été défini (d’où l’erreur).

Certains noms réservés du langage sont interdits comme nom de variable :

1
2
3
bronze = 3
argent = 2
or = 1
  • Ligne 3 : or est un mot-clé du langage (qui signifie ou en anglais).

Le seul caractère non-alphanumérique autorisé est le blanc souligné :

1
2
paris_2024 = 42
print(paris_2024)
  • Ligne 3 : or est un mot-clé du langage (qui signifie ou en anglais).

Pour saisir un blanc souligné, taper simultanément AltGr + 8.

Nom ou variable non reconnus

Une variable qui est accédée sans avoir été affectée au préalable n’est pas reconnue :

1
2
R = 10
print(2 * pi * R)
3
NameError: name 'pi' is not defined
  • Ligne 2 : la variable pi est utilisée mais n’a jamais été défini auparavant.
  • Ligne 3 : le nom de variable pi n’est pas reconnu d’où le message NameError qui doit s’interpréter par : « nom inconnu ».

Ce type d’erreur provient parfois d’une erreur de saisie du code (une « coquille ») :

1
2
toto = 42
print(totot * 10)
3
NameError: name 'totot' is not defined

Ce phénomène s’applique aussi à des noms (par exemple, de fonctions « officielles » du langage), pas seulement des variables :

1
2
toto = 42
printf(toto * 10)
3
NameError: name 'printf' is not defined
  • Ligne 2 : le programmeur a saisi printf au lieu de print.

Réaffectation de variable

Lorqu’un calcul avec une variable x est suivie de la modification de la valeur de la variable x, on dit que x a subi une réaffectation :

1
2
3
x = 42
x = 2 * x + 10
print(x)
4
94
  • Ligne 2 : l’expression 2 * x + 10 est évaluée et la valeur obtenue (94) est réaffectée à x. Ce type d’affectation (ligne 1 vs ligne 2) s’appelle une réaffectation. La valeur initiale d’affectation (ici 42) est « perdue ».

Augmenter de 1 la valeur d’une variable (comme toto ci-dessous) s’appelle une incrémentation :

1
2
3
4
5
toto = 42
print(toto)

toto = toto + 1
print(toto)
6
7
42
43
  • Ligne 4 : l’expression toto + 1 est évaluée et la valeur obtenue (43) est réaffectée à toto.

La nécessité d’effectuer une réaffectation est extrêmement courante.

Notions sur les constantes

Soit le code Python suivant :

1
2
3
4
z = 31
a = 42 * z + 81
z = "toto"
pi = 3.14159

Dans ce code,

31, 42, 81, "toto" ou 3.14159

sont des constantes du langage Python, Elles sont dites parfois littérales car leur façon de s’écrire dans le code permet de connaître immédiatement leur valeur, sans faire aucune opération. Par contre,

42 * z + 81

N’est PAS une constante (c’est juste une expression qui utilise des constantes). Les constantes sont des briques élémentaires (parmi d’autres) des « écritures » d’un programme.

Pour afficher une constante présente dans un code Python, on utilise la fonction print.

1
2
3
4
5
6
7
8
9
a=42
print(a)

z="toto"
print(z)
print("toto")

pi = 3.14159
print(pi)
 9
10
11
12
42
toto
toto
3.14159
  • Lignes 5 ou 9 : instruction d’affichage du contenu d’une variable dont le contenu (lignes 4 ou 8) est une constante.
  • Ligne 6 : on peut aussi obtenir l’affichage de la constante sans l’avoir placée dans une variable.
  • Lignes 10-13 : les affichages correspondants.

Constantes entières

Les constantes entières figurant textuellement dans un code , telles que 421, peuvent être précédées d’un signe - pour désigner un entier négatif ou d’un signe +, facultatif et en général omis :

1
2
print(-42)
print(+421)
3
4
-42
421

Toute constante entière, écrite de la façon habituelle avec des chiffres entre 0 et 9, comme 421 ou 0 est interprétée par défaut comme écrite en base 10.

Attention à ne pas placer involontairement un 0 comme premier chiffre d’une constante entière, comme on le ferait pour certaines dates (par exemple 01 dans la date 19/01/2038) sinon on obtient un message d’erreur :

1
print(042)
2
3
4
5
  File "_.py", line 1
    print(042)
            ^
SyntaxError: invalid token

Grands entiers

On peut effectuer tout type d’opération arithmétique avec des entiers aussi grands qu’on le souhaite. Une opération arithmétique ne peut jamais créer d”« overflow » comme c’est le cas en C ou Java où les entiers sont codés sur un nombre prédéfini de bits.

Exemple d’usage de grands entiers :

1
2
3
a = 8596125023601452569859
b = 7012365895410232252363
print(a * b)
4
60279173948185303803365326980576772175326817

Constantes flottantes

La présence d’un point dans une constante numérique donne à la constante le type flottant. Le point est, dans ce cas, l’équivalent de notre virgule décimale :

1
print(3.14)
2
3.14
  • Ligne 1 : le nombre 3.14 est une constante flottante ; il y a des chiffres de part et d’autre du point
  • Ligne 2 : l’affichage est obtenu via la fonction print.

Il est parfois possible qu’aucun chiffre ne précède ou ne suive le point :

1
2
print(1.)
print(.25)
3
4
1.0
0.25
  • Ligne 1 : 1. est équivalent à 1.0
  • Ligne 2 : .25 est équivalent à 0.25

Le but de ce type d’écriture est juste d’alléger la saisie du code.

En France, le séparateur décimal est une virgule. Il faut cependant toujours utiliser un point pour désigner le séparateur d’une constante flottante. Voici un exemple de comportement inattendu :

1
2
pi = 3,14
print(pi + 1)
3
TypeError: can only concatenate tuple (not "int") to tuple
  • Ligne 1 : on déclare le nombre pi sous la forme 3,14 au lieu de 3.14.
  • Lignes 2 : On veut ajouter 1 à pi (on devrait obtenir 4,14) mais le programme est interrompu.

On peut faire précéder une constante flottante d’un signe - ou + :

1
2
print(-3.14)
print(+3.14)
3
4
-3.14
3.14

Types de base

Les objets manipulées par un programme Python ont un type, au sens d’un langage de programmation : un type correspond à une catégorie d’objets (entiers, nombres réels, valeurs logiques, etc).

Voici quelques exemples de types usuels :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
print(42)
print(4 + 6)
print(-5 * 2)

print(421.5)
print(2.7 + 10)

print(421 > 42)
print(421 < 42)

print("toto")
12
13
14
15
16
17
18
19
42
10
-10
421.5
12.7
True
False
toto
  • Lignes 1-3 : type entier. Les entiers peuvent être positifs comme négatifs.
  • Lignes 5-6 : type flottant. Pour simplifier, il s’agit de nombres dit « à virgule », ci-dessus représentés en base 10. Le point utilisé dans le nombre représente notre virgule décimale («  flottant  » fait allusion à la notion de virgule «  flottante  »).
  • Lignes 8-9 et 17-18 : type booléen. Une expression de type booléen a une valeur de vérite True ou False.
  • Lignes 11 : le type chaîne. En première approximation, une chaîne représente une suite de caractères. Dans l’exemple, pour que Python reconnaisse le mot toto comme une donnée de type chaîne, on entoure le mot d’une paire de guillemets.

Même valeur et types différents

Des objets peuvent avoir même valeur et des types différents. Par 10.0 et 10 ont même valeur

1
2
3
4
a=10
b=10.0

print(a, "==", b, ":", a==b)
5
10 == 10.0 : True

mais ils ont des types différents ce qui se traduit par des comportement différents vis à vis de certains opérateurs.

Par exemple, si on multiplie 10 par un très grand entier N, on ne trouve pas le même résultat que si on multiplie 10. et le grand entier N, comme le code suivant le montre :

1
2
3
4
5
a=10
b=10.0
N=123456789101234567

print(a*N == b*N)
6
False

Variables et typage

Un nom de variable n’est pas associé à un type fixé

1
2
3
4
a = 2020
print(a)
a = 3.14
print(a)
5
6
2020
3.14
  • Ligne 1 : l’étiquette a se réfère d’abord à un entier.
  • Ligne 3 : l’étiquette a se réfère ensuite à un flottant.

Une variable n’a pas de type. Ce qui a un type est l’objet placé en mémoire et que la variable référence.

Une variable peut étiqueter un objet de n’importe quel type.

Par exemple, on peut placer une variable sur le nom d’une fonction :

1
2
p = print
p("bonjour")
3
"bonjour"

Les fonctions built-in

Python propose, par défaut, des fonctions prêtes à l’emploi (les fonctions dites « built-in ») et qui permettent de faire des opérations courantes en programmation : afficher, trier une liste, trouver le plus grand nombre d’une liste, calculer la longueur d’une chaîne de caractères, etc.

Exemple

1
print(max(81, 12, 31, 82, 65))
2
82
  • Ligne 1 : max est une fonction built-in. Elle renvoie le plus grand élément des nombres qu’on lui transmet.

La fonction built-in la plus utilisée est probablement la fonction print.

Indentation accidentelle

Le placement d’espaces horizontaux en début de ligne n’est autorisé que dans certaines circonstances très strictes.

En cas de non respect de ces règles, on obtient une interruption du programme :

1
2
x = 3000 - (2038 - 38)
 print("Bonjour !", x)
3
4
5
6
  File "__.py", line 2
    print("Bonjour !", x)
    ^
IndentationError: unexpected indent

Le message IndentationError signifie que des espaces en début de ligne sont mal placées.

Placer des commentaires

Il est possible d’annoter son code-source par des commentaires personnels. Voici un exemple de code-source commenté :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Mon joli code


# Voici un exemple
# d'addition
a=4+2

    # on va afficher le résultat
print(a) # affichage
# affiche 6

Un commentaire Python est introduit par un caractère dièse comme ceci : # (cf. ligne 4 par exemple).

Tout ce qui suit un caractère # est un commentaire. Le code commentaire.py contient 6 commentaires.

La présence de commentaires n’a pas d’impact sur l’exécution du code et ils sont supprimés du code avant l’exécution de celui-ci. Le code ci-dessus est exactement équivalent au code suivant :

commentaires_retires.py

1
2
a=4+2
print(a)

Les commentaires sont destinés au programmeur lui-même ou à un autre programmeur qui va lire le code afin d’en expliquer certaines parties.

Opérations sur les nombres

Voici quelques opérations usuelles que l’on peut effectuer entre nombres réels (pas seulement entiers).

On peut calculer des expressions mathématiques avec des parenthèses :

1
2
3
4
print(-421)
print(2 * 10 + 15)
print((2 + 3) * (8 + 2))
print(42.1 / 10)
5
6
7
8
-421
35
50
4.21
  • Lignes 4 et 8 : on effectue la division « exacte » de 42.1 par 10.

Certains calculs nécessitent le placement de parenthèses. Par exemple, en mathématiques, on écrit couramment

\(\displaystyle\frac a{bc}.\)

En Python, cela NE se traduit PAS par a / b * c mais par a /(b * c) :

1
2
3
x = 100 / 10 * 5
y = 100 / (10 * 5)
print(x, y)
4
50.0 2.0

En cas de doute dans un calcul, placer des parenthèses même s’il est possible qu’elles ne soient pas indispensables. Ainsi, la fraction

\(\displaystyle \frac{\frac{100.0}{5}}4\)

sera traduite par (100. / 5) / 4 :

1
2
3
x = (100 / 5) / 4
y =  100 / 5 / 4
print(x, y)
4
5.0 5.0

Ne pas utiliser de crochets à la place des parenthèses car les crochets ont un autre sens en Python.

Pour calculer une puissance \(x^y\), on écrit x ** y dans le code Python :

1
2
3
print(10 ** 2)
print(6.25 ** 0.5)
print(0 ** 0)
4
5
6
100
2.5
1

Les nombres \(x\) et \(y\) peuvent n’être pas des entiers.

En particulier, x ** 0.5 représente \(\sqrt x\), la racine carrée de \(x\) (lignes 2 et 5)

Les puissances de 10

Python permet en particulier de manipuler aisément les puissances de 10.

1
2
print(10000000000000)
print(10**13)
3
4
10000000000000
10000000000000
  • Ligne 1 : écriture, relecture délicates
  • Ligne 2 : écriture, relecture immédiates

L’utilisation de puissances de 10 permet d’éviter des difficultés de saisie et de lecture dues à un grand nombre de zéros. Par exemple, pour écrire

  • deux millions, utiliser la notation 2 * 10 ** 6
  • deux milliards, utiliser la notation 2 * 10 ** 9

Division flottante

Pour obtenir la division exacte du nombre a par le nombre b, on utilise tout simplement la syntaxe a / b :

1
2
print(366/ 12)
print(3.14 / 2)
3
4
30.5
1.57

Les nombres a et b peuvent aussi bien être des entiers que des flottants. Le résultat a / b sera toujours de type flottant.

Utiliser des variables

Quand on veut « récupérer » (autrement dit sauvegarder) le résultat d’un calcul, on le place dans une nouvelle variable :

1
2
3
4
5
6
x = 42
y = 5
z = (x * y + 5) * (x ** 2 + y **2 ) - 100
u = (z - 10000) * x

print(u)
7
15730470
  • Lignes 3 : on stocke sous le nom de z le résultat d’un calcul en mémoire
  • Lignes 4 : on stocke sous le nom de u le résultat d’un autre calcul
  • Ligne 6 : on affiche le contenu de la variable

Une expression utilisant une variable ne modifie pas le contenu de la variable :

1
2
3
toto = 42
print(toto + 1)
print(toto)
3
4
43
42
  • Ligne 2 : on ajoute 1 à la valeur de toto. Le résultat (ici 43) est affichée mais ce calcul est « perdu » puisqu’il n’est pas replacé dans une variable.
  • Ligne 5 : bien qu’on ait ajouté 1 à toto, le contenu de la variable toto reste inchangé par rapport à sa valeur initiale.

Exercice type : Volume de la sphère

Le volume de la sphère est

\(V=\frac 43\pi r^3\)

Écrire en Python une formule (avec des variables) qui calcule le volume \(V\) d’une sphère de rayon \(r\). On posera pi = 3.14. Tester avec \(r = 10\).

Solution

D’abord, écrire la formule de manière purement formelle ne fonctionne pas :

1
2
v = 4/3 * pi * r**3
print(v)
3
4
5
6
7
8
NameError                                 Traceback (most recent call last)
<ipython-input-32-b6f8fcc9c76e> in <module>()
----> 1 v = 4/3 * pi * r**3
      2 print(v)

NameError: name 'pi' is not defined

Python n’est pas un outil de calcul formel.

Il faut initialiser r mais aussi \(\pi\) :

1
2
3
4
5
pi = 3.14

r=10
v = 4/3 * pi * r**3
print(v)
6
4186.666666666667

Pour tester d’autres valeurs, le plus simple est de changer r dans le code-source et de relancer l’exécution du code.

Opérations mixtes entre flottants et entiers

Lorsqu’on effectue un ensemble d’opérations arithmétiques qui font intervenir des entiers et des flottants, le résultat est de type flottant :

1
2
3
4
5
x = 1.0
y = 42

print(x * y)
print(x - x)
6
7
42.0
0.0
  • Lignes 4 et 5 : bien que les valeurs des flottants représentent des nombres entiers, le résultat est de type flottant

Opérateurs « égale à » et « différent de »

Opérateur ==

On peut tester l’égalité de valeur de deux objets avec l’opérateur == :

1
2
print(42 == 21 + 21)
print(42 == 10 + 10)
3
4
True
False
  • Lignes 3 : si les valeurs sont égales l’opérateur == ligne 1 renvoie la valeur logique True
  • Ligne 4 : si les valeurs comparées ne sont pas égales (42 et 20) l’opérateur == renvoie False.

Il faut effectivement écrire deux fois de suite le signe =, sans espace entre les deux.

Quand on lit True (ligne 1, ligne 4), il faut comprendre que l’expression 42 == 21 + 21 est un « machin » (un objet pour être correct) qui vaut True. Le code ci-dessous permet peut-être de mieux le comprendre :

1
2
machin = (42 == 21 + 21)
print(machin)
3
True

Opérateur !=

Pour tester si deux objets ont des valeurs distinctes, on utilise l’opérateur != (lire : différent de). C’est l’opérateur « contraire » de == :

1
2
print(42 != 21 + 21)
print(42 != 10 + 10)
3
4
False
True

Comparaison de nombres

Le langage Python dispose d’opérateurs permettant d’effectuer des comparaisons de nombres :

1
2
3
4
print(42 > 24)
print(42 <= 24)
print(3.14159 < 2.71828)
print(24 >= 2 * 12)
5
6
7
8
True
False
False
True

On peut comparer des nombres au sens des opérateurs mathématiques suivants :

\(< \quad \leq \quad >\quad \geq\)

En Python, on utilise les opérateurs suivants :

<, <=, > et >=

Une comparaison renvoie un booléen True ou False (Vrai ou Faux) qui précise si l’inégalité écrite est vraie ou fausse.

Encadrement

On peut utiliser les opérateurs de comparaison en les enchaînant, comme on le fait usuellement en mathématiques :

1
2
print(42 < 81 < 100 <= 512)
print(42 < 81 < 100 < 100)
3
4
True
False

Comparaison de flottants

L’arithmétique en nombres flottants est approchée. L’exemple ci-dessous illustre le type de problème rencontré :

1
print(6 * 0.7 == 4.2)
2
False
  • Ligne 1: mathématiquement, \(6\times 0,7 = 4,2\)
  • Ligne 2 : pourtant, Python ne considère pas les deux nombres comme identiques !

De même :

1
print(42/6==4.2/0.6)
2
False

Cette limitation provient l’impossibilité de représenter exactement en base 2 et avec un nombre limité de bits certains nombre réels.

D’où la conséquence suivante :

Règle fondamentale : on n’utilise jamais l’opérateur == pour comparer deux flottants.

Confusion entre égalité et affectation

Le signe = est le signe de l’affectation. Il ne faut pas le confondre avec l’opérateur == d’égalité de valeurs. C’est un source fréquente d’erreur d’inattention, y compris chez les programmeurs non débutants.

Assez souvent, la confusion déclenche un message d’erreur :

1
2
x == 42
print(x)
2
3
4
5
Traceback (most recent call last):
  File "_.py", line 1, in <module>
    x == 42
NameError: name 'x' is not defined
  • Ligne 1 : confusion de == avec = : la ligne examine si les valeurs de x et 42 sont égales mais x n’a pas été défini.
  • Ligne 6 : la nature de l’erreur est confirmée par le message.

Autre erreur possible :

1
2
x = 42
print(x = 421)
2
3
4
5
Traceback (most recent call last):
  File "egalite_vs_affectation.py", line 2, in <module>
    print(x = 421)
TypeError: 'x' is an invalid keyword argument for this function
  • Ligne 2 : confusion de = avec == (une affectation n’est pas une expression donc on ne peut pas l’afficher)
  • Lignes 3-6 : l’erreur est plus difficile à interpréter et nécessite des connaissances plus poussées sur la fonction print et les fonctions en général.

Mais parfois, il n’y a aucun déclenchement d’erreur :

1
2
3
4
x = 42
print(x)
x == 100
print(x)
5
6
42
42
  • Ligne 3 : sans doute le programmeur voulait-il écrire une nouvelle affectation x = 100. Mais cette erreur de programmation ne déclenche aucune erreur d’exécution.

Multiples, division entière

On rappelle quelques notions d’arithmétique élémentaire. En particulier, la notion de division entière, vue à l’école primaire mais dont le concpet n’est pas toujours maîtrisé et qui est essentielle en programmation.

Multiples

Les nombres qui sont les résultats dans une table de multiplication sont appelés des multiples. Par exemple, les 10 premiers multiples de 9 sont :

 1 x  9 =   9
 2 x  9 =  18
 3 x  9 =  27
 4 x  9 =  36
 5 x  9 =  45
 6 x  9 =  54
 7 x  9 =  63
 8 x  9 =  72
 9 x  9 =  81
10 x  9 =  90

Plus généralement, tout multiple de 9 est de la forme \(9\times k\)\(k\) est un entier. Par exemple, \(720 = 9\times 80\) est un multiple de \(9\).

Si un nombre \(n\) est un multiple de 9, il est équivalent de dire que 9 est un diviseur de \(n\) ou encore que \(n\) est divisible par 9.

Réciproquement, soit le problème suivant :

474 est-il un multiple de 8 ?

Pour répondre, il suffit de faire la division à la façon de « l’école primaire » de 474 par 8 :

../../../_images/division-legende.png

La division de l’école primaire

Si le reste de cette division vaut 0 autrement dit, si la division tombe juste, c’est que la réponse est oui et si le reste est non nul, la réponse est non. Ici, la division de 474 par 8 admet 2 pour reste, en sorte que la réponse est non.

La division de l’école primaire est en fait appelée division entière. La division entière fournit un reste et un quotient. Par exemple, la division entière de 474 par 8 admet 59 pour quotient et 2 pour reste.

Plus généralement, quand on effectue la division entière de \(a\) par \(b\), on obtient un quotient \(q\) et un reste \(r\). Noter que \(r\) vérifie : \(0\leq r< b\) autrement dit le reste est toujours plus petit que le diviseur. Et bien sûr, on a

\(\ds a=bq+r\)

Noter qu’avec les notations précédentes, le plus grand multiple de \(b\) inférieur ou égal à \(a\) est exactement \(a-r\).

La division entière est différente de la division dite « exacte ». La division exacte ne fournit qu’un quotient, supposé exact. Par exemple, la division exacte de 474 par 8 est 59.25, ce qui s’écrit

\(\frac {474}{8}=59.25\)

En réalité, très souvent, le quotient obtenu est une valeur approchée : par exemple, on écrit couramment \(\frac {474}{7}=67.71\) bien qu’en fait \(67.71\) ne soit qu’un approximation de la division de 474 par 7, qui « ne tombe pas juste ».

La notion de multiple donne fréquemment lieu à des questions de programmation.

Quotient et reste de division entière

Le quotient entier de l’entier a par l’entier b est obtenu par l’opération a // b (double oblique) :

1
print(42 // 10)
2
4
  • Ligne 1 : Noter le double slash pour effectuer la division entière, et non 42 / 10 .
  • Ligne 2 : noter que la réponse n’est pas 4,2 (il ne s’agit pas de la division exacte).

Le reste entier de la division de l’entier a par l’entier b est noté a % b :

1
print(42 % 10)
2
2
  • Ligne 1 : le calcul du reste se fait avec l’opérateur % « pourcent ».

L’opérateur % est parfois appelé opérateur modulo.

../../../_images/division-legende-operateurs.png

Les opérateurs de division

Division par zéro

Toute forme de division par 0 est interdite et renvoie une erreur :

1
print(42 // 0)
2
3
4
5
Traceback (most recent call last):
  File "division_par_zero.py", line 1, in <module>
    print(42 // 0)
ZeroDivisionError: division by zero
  • Ligne 1 : quotient par 0 : interdit

De même :

1
print(42 % 0)
2
3
4
5
Traceback (most recent call last):
  File "reste_par_zero.py", line 1, in <module>
    print(42 % 0)
ZeroDivisionError: integer division or modulo by zero
  • Ligne 1 : reste en divisant par 0 : interdit

Division entière et quotient exact

Si \(b\) est un entier multiple de l’entier \(d\), la division exacte \(b/d\) a même valeur (mathématique) que le quotient entier de \(b\) par \(d\). Mais en Python, le quotient exact sera de type flottant tandis que le quotient entier de type entier :

1
2
3
4
5
6
7
b = 42
d = 6

print(b // d)
print(b % d)

print(b / d)
 8
 9
10
7
0
7.0
  • Lignes 5 et 9 : b est bien un multiple de d puisque le reste est nul.
  • Lignes 8 et 10 : le quotient entier et le quotient exact ont même valeur mathématique mais pas même type.

Bien que les valeurs des quotients soient exactes, la différence de type peut entraîner des erreurs. Par exemple, la fonction range, qui sera vue plus tard, n’admet en arguments que des objets de type entier :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
b = 42
d = 6

print(b // d)
print(b % d)

print(b / d)


print(list(range(b // d)))
print("----------------------------")


# Va entraîner une erreur
print(list(range(b / d)))
16
17
18
19
20
21
22
23
24
7
0
7.0
[0, 1, 2, 3, 4, 5, 6]
----------------------------
Traceback (most recent call last):
  File "division_entiere_et_quotient_exact.py", line 13, in <module>
    print(list(range(b / d)))
TypeError: 'float' object cannot be interpreted as an integer

Il se peut même que les quotients calculés soient différents alors que les valeurs mathématiques soient égales :

1
2
3
4
5
6
b = 9563862022090661
d = 1
print(b // d)
print(b % d)

print(b / d)
7
8
9
9563862022090661
0
9563862022090660.0

En conclusion, si on cherche le quotient exact d’un entier \(b\) par un de ses diviseurs, on utilisera l’opérateur de division entière.

Traduire « être multiple » en Python

Pour savoir si un entier \(n\) est pair, on examine le reste \(r\) de \(n\) dans la division par 2. Si \(r\) vaut 0, l’entier \(n\) est pair et si le reste vaut 1 alors \(n\) est impair. Pour calculer \(r\), on utilise l’opérateur % (modulo) :

1
2
3
4
5
r = 2030 % 2
print(r == 0)

r = 421 % 2
print(r == 0)
6
7
True
False
  • Lignes 1-2 : le reste 0 montre que 2030 est bien pair
  • Lignes 3-4 : le reste 1 montre que 421 est bien impair.

De même, pour savoir si un entier \(n\) est multiple de 10, on calcule le reste de \(n\) par 10 et on examine si ce reste vaut 0 ou pas :

1
2
3
4
5
r = 2020 % 10
print(r == 0)

r = 421 % 10
print(r == 0)
6
7
True
False

D’une façon générale, pour traduire que :

  • d est diviseur de a
  • a est un multiple de d

on examine si le reste a % d == 0 vaut True ou False. On peut aussi examiner si a % d != 0.

Affichage multiple

Il est possible d’afficher plusieurs objets sur une même ligne à l’aide d’un seul appel à print.

1
print("toto", 42+100)
2
toto 142
  • Ligne 1 : on affiche la chaîne toto et le nombre 42+100.
  • Ligne 2 : les deux objets à afficher (toto et le nombre 152) sont séparés exactement d”un seul espace.

Les objets sont affichés sur une même ligne, séparés par un seul espace. Placer plus ou moins d’espacements dans l’écriture de l’appel à la fonction print ne modifie nullement l’espacement affiché :

1
print("toto"     ,        42+100)
2
toto 142
  • Ligne 1 : lors de l’écriture de l’appel dans le code-source, de nombreux espaces ont été placés entre les deux objets à afficher.
  • Ligne 2 : l’espacement à l’affichage reste pourtant d’une espace.

La possibilité d’affichage multiple s’applique aussi à des expressions dépendant de variables :

1
2
3
x = 42
y = 10
print(x + y, x - y)
4
52 32

Affichage amélioré

Le programmeur a parfois besoin de rendre plus lisible des résultats à afficher dans un terminal ou une zone d’output. Voici un exemple sommaire d’une telle situation :

afficherLisible.py

1
2
3
4
a = 100
b = 42
print(a + b, a - b)
print("L'addition -> ", a + b, "La soustraction ->", a - b)
5
6
142 58
L'addition ->  142 La soustraction -> 58
  • Ligne 3 et ligne 5 : affichage peu lisible.
  • Ligne 4 et ligne 6 : affichage dont le contenu est plus facilement interprétable.

Affichage et débogage

En particulier, pour vérifier (visuellement) la justesse d’un programme ou pour mieux en comprendre le fonctionnement, il est parfois utile de faire des affichages des variables et des valeurs calculées :

1
2
3
4
5
6
a = 100
b = 42
print("a = ", a, ",", "b = ", b)
print("---------------------")
print("a + b  = ", a + b)
print("a - b  = ", a - b)
 7
 8
 9
10
a =  100 , b =  42
---------------------
a + b  =  142
a - b  =  58

L’action de rechercher les erreurs (les « bugs » ou, en français, les « bogues ») que contient un programme s’appelle le débogage. Le placement d’instructions d’affichage dans certaines parties bien choisies d’un code-source en cours de réalisation dans le but de mieux comprendre comment il s’exécute et ce que valent les variables pendant l’exécution du code est une forme très fréquente de débogage (bien que très rudimentaire).

Afficher un message complexe

Comme un texte est une suite de lignes, la fonction print permet d’afficher des messages plus élaborés :

1
2
3
4
5
print("Voici les couleurs")
print()
print("+----------+----------+----------+")
print("|   Rouge  |  Vert    |  Bleu    |")
print("+----------+----------+----------+")

qui affiche

1
2
3
4
5
Voici les couleurs

+----------+----------+----------+
|   Rouge  |  Vert    |  Bleu    |
+----------+----------+----------+

Noter, qu’en général, ce type de message est compliqué à construire et à maintenir.

Affichage et forcer un passage à la ligne

Pour séparer deux affichages bien distincts d’un même programme, le programmeur veut parfois placer un ou plusieurs sauts de ligne entre les parties à afficher. Par exemple, supposons qu’il veuille afficher

un
deux
trois


1
2
3

Il est sans effet de passer des sauts de lignes dans le code-source. Ainsi, le code suivant

1
2
3
4
5
6
7
8
print("un")
print("deux")
print("trois")


print(1)
print(2)
print(3)

affichera

un
deux
trois
1
2
3

(noter les sauts de lignes dans le code-source aux lignes 4-5).

Une solution au problème est la suivante :

1
2
3
4
5
6
7
8
print("un")
print("deux")
print("trois")
print()
print()
print(1)
print(2)
print(3)
 9
10
11
12
13
14
15
16
un
deux
trois


1
2
3
  • Lignes 4-5 : appel à la fonction print sans argument (une paire de parenthèses vides).
  • Lignes 12-13 : chaque appel print() effectue un saut de ligne à l’affichage ce qui « allège » l’affichage final.

Affichage implicite dans Jupyter Notebook

Dans Jupyter Notebook, la valeur d’une expression peut parfois être affichée sans que la fonction print ne soit utilisée. Plus précisément, une expression placée en dernière ligne d’une cellule de code comme on voit ci-dessous :

../../../_images/jupyter_affichage_implicite.png

provoque l’affichage de la valeur de l’expression. Ainsi, dans le code,

1
2
3
n = 42
n + 1
10 * n

la ligne 3 provoque l’affichage de 420 et c’est assez logique, cela cadre avec la modalité interactive de l’interface Jupyter Notebook. La ligne n + 1 ne provoque aucune affichage (car ce n’est pas la dernière ligne).

Une affectation simple n’étant pas une expression, elle ne provoque pas d’affichage :

n = 42
# aucun affichage produit

L’expression doit être hors-bloc, sinon rien n’est affiché, comme dans l’exemple suivant :

if True:
    42
# aucun affichage produit

Si l’expression a pour valeur None, rien n’est affiché non plus :

[4, 5, 6].append(42)
# aucun affichage produit

Pour forcer un affichage, utiliser la fonction print :

n = 42
print(n)
10 * n
42
420

La bibliothèque standard

Le langage Python intègre la possibilité, par exemple, de trier une liste d’entiers :

1
print(sorted([5,19,14,12,21]))
2
[5, 12, 14, 19, 21]
  • Ligne 1 : la liste 5,19,14,12,21 n’est pas triée.
  • Ligne 2 : la liste [5, 12, 14, 19, 21] est triée.

À l’inverse de la fonction de tri sorted, certaines fonctions, comme la partie entière d’un nombre, ne peuvent être utilisées directement par le langage Python mais sont disponibles si on fait appel à ce qu’on appelle la « bibliothèque standard » de Python.

Ainsi, voici comment on peut calculer en Python des parties entières :

1
2
3
4
from math import floor

print(floor(4.21))
print(floor(-4.21))
5
6
4
-5
  • Ligne 1 : on doit importer la fonction floor du « module » math de la bibliothèque standard.
  • Lignes 3 et 4 : on appelle la fonction de partie entière floor importée du module math.

La notion de bibliothèque standard

La bibliothèque standard de Python est livrée avec le langage Python mais ne fait pas partie du langage en tant que tel. Elle étend les possibilités du langage.

Les fonctionnalités de la bibliothèque standard sont regroupées en entités que l’on appelle des modules. Ainsi, les fonctionnalités mathématiques sont disponibles dans le module math.

Pour accéder depuis du code Python à une fonctionnalité d’un module de la bibliothèque standard, il faut importer cette fonctionnalité dans le code Python par une instruction d’importation (cf. ligne 1 ci-dessus).

La bibliothèque standard contient beaucoup d’autres modules que le module math. Voici quelques exemples de modules disponibles :

Module Fonctionnalité
math Fonctions mathématiques
random Manipuler des nombres aléatoires
decimal Résultats exacts avec les nombres décimaux
datetime Gestion des dates, des durées
os.path, shutil Manipuler le système de fichiers
Tkinter Interfaces graphiques

Un module de la bibliothèque standard est dit module standard.

De nombreuses fonctionnalités de la bibliothèque standard concernent des questions spécialisées et/ou techniques et sont réservés à des programmeurs de niveau avancé voire professionnel.

Importer une fonctionnalité standard

Soit le code suivant qui importe la fonction floor du module standard math.

1
2
3
from math import floor

print(floor(4.21))
4
4

Ligne 1 : on n’importe qu’une seule fonctionnalité, la fonction floor.

Pour qu’un code Python puisse utiliser une fonctionnalité, par exemple la fonction floor, ce code doit importer (avec une instruction import) la fonctionnalité du module ad hoc.

Si on n’importait rien, cela produirait une erreur :

1
2
z = floor(421.2020)
print(z)
3
4
5
6
----> 1 z = floor(421.2020)
      2 print(z)

NameError: name 'floor' is not defined
  • Ligne 1 : Faute d’importation, le nom floor n’est pas reconnu.

On a importé une fonction du module math mais un module peut, en général, proposer d’autres types d’objets à importer, par exemple des constantes. Ainsi, le module math dispose de la constante mathématique \(\pi\) :

1
2
3
from math import pi

print(pi)
4
3.141592653589793

Le Hasard en Python

Un nombre aléatoire est un nombre tiré au hasard. Plus généralement, l’adjectif aléatoire se réfère à ce qui est le résultat du hasard.

Le module standard random gère l’aléatoire en Python.

Le code ci-dessous génère un entier aléatoire entre 1 et 49, comme pour un tirage d’une boule au loto :

1
2
3
4
from random import randint

a = randint(1,49)
print(a)
5
42
  • Ligne 1 : la bibliothèque standard Python dispose d’un module de création d’objets aléatoires. Ce module s’appelle random. Le module random « possède » une fonction randint. La ligne 1 permet au programme de faire appel à la fonction randint.
  • Ligne 3 : le tirage est effectué grâce à la fonction randint. La fonction randint renvoie ici un nombre (aléatoire) entre 1 et 49, bornes comprises.
  • Lignes 4 et 5 : le résultat du tirage aléatoire.

Fonction randrange

Dans l’exemple ci-dessous, on effectue un tirage aléatoire de 6 entiers \(\mathtt{n}\) vérifiant \(\mathtt{1 \leq n < 50}\) (comme au loto en France) :

1
2
3
4
5
6
7
8
from random import randrange

print(randrange(1, 50))
print(randrange(1, 50))
print(randrange(1, 50))
print(randrange(1, 50))
print(randrange(1, 50))
print(randrange(1, 50))
 9
10
11
12
13
14
14
15
47
45
38
12

La fonction randrange est une fonction du module random. L’usage de la fonction randrange nécessite donc une instruction d’importation, cf. ligne 1 ci-dessus.

Un appel randrange(a, b) renvoie un entier aléatoire n tel que \(\mathtt{a\leq n < b}\)\(\mathtt{a}\) et \(\mathtt{b}\) ont des valeurs entières (on notera que la borne en \(\mathtt{b}\) est stricte)

Pour effectuer un tirage par pile ou face, on utilisera randrange(2).

De même, pour simuler un dé, on utilisera randrange(6) :

1
2
3
4
5
from random import randrange

# Tirage de dé à 6 faces
de_1_6 = 1+randrange(6)
print(de_1_6)
6
3

Fonction randint

La fonction randint fournie par le module standard random génère un entier aléatoire entre deux bornes entières a et b, bornes incluses.

1
2
3
from random import randint

print(randint(1, 49))
4
40

Un appel randint(a, b) se fait toujours avec deux arguments, entiers et renvoie un entier aléatoire \(\mathtt{n}\) tel que \(\mathtt{a\leq n\leq b}\).

Pour effectuer un tirage par pile ou face, on utilisera randint(1, 2).

De même, pour simuler un dé, on utilisera randint(1,6) :

1
2
3
4
5
from random import randint

# Tirage de dé à 6 faces
de_1_6 = randint(1, 6)
print(de_1_6)
6
3