Objectifs du chapitre
À la fin de ce chapitre, vous serez capable de:
- expliquer ce qu'est un programme, ce que fait un interpréteur, et utiliser aussi bien l'invite interactive
>>>qu'un fichier de script; - créer des variables par affectation, les réaffecter, et distinguer l'affectation
=de la comparaison==; - nommer correctement vos variables et reconnaître un nom que Python refuse;
- reconnaître les quatre types de base (
int,float,str,bool), les interroger avectype()et les convertir avecint(),float()etstr(); - calculer avec les opérateurs arithmétiques, en particulier distinguer la division exacte
/de la division entière//et du reste%; - dialoguer avec l'utilisateur au moyen de
print()etinput(), en convertissant toujours ce que renvoieinput(); - lire une trace d'erreur ligne par ligne et identifier les quatre erreurs les plus fréquentes du débutant.
Qu'est-ce qu'un programme?
D'une recette à un programme
Vous savez déjà écrire des programmes: une recette de cuisine, un mode d'emploi de meuble en kit, les consignes que vous laissez à quelqu'un qui doit arroser vos plantes sont des suites d'instructions destinées à être exécutées par un autre, dans l'ordre, sans que celui qui les exécute ait besoin de comprendre pourquoi. La seule différence avec un programme informatique, c'est le destinataire: la machine ne complète rien, ne devine rien, ne rattrape aucune ambiguïté. «Ajoutez du sel» est une instruction acceptable pour un être humain et inutilisable pour un ordinateur, qui demandera combien, de quel sel, et dans quoi.
C'est cette exigence d'exactitude qui rend la programmation à la fois difficile au début et instructive ensuite. Écrire un programme oblige à décomposer une tâche jusqu'à ce que chaque étape soit sans reste, et cette décomposition est un exercice intellectuel qui se transporte bien au-delà de l'informatique. Vous allez passer beaucoup de temps, dans ce cours, à découvrir que vous croyiez savoir faire quelque chose que vous ne saviez en réalité pas décrire.
Le mot instruction mérite d'être retenu en français et en anglais, car tous les messages d'erreur que vous allez rencontrer sont en anglais. Ce cours vous donnera systématiquement les deux formes.
Le langage et l'interpréteur
Un processeur ne comprend que des suites de nombres. Personne n'écrit plus de programmes sous cette forme depuis les années 1950. On écrit dans un langage de haut niveau, c'est-à-dire un langage proche des notations humaines, et un autre programme se charge de la traduction. Nous utiliserons Python, créé par Guido van Rossum au début des années 1990, dans sa version 3.11 ou plus récente: les sorties reproduites dans ce cours ont toutes été produites par Python 3.13.
Python est un langage interprété. Cela signifie qu'un programme appelé l'interpréteur lit votre texte instruction par instruction et exécute chacune immédiatement, au lieu de traduire d'abord tout le fichier en langage machine puis de lancer le résultat, comme le font les langages compilés (C, C++, Rust). La différence est visible dans votre travail quotidien: vous pouvez essayer une seule ligne et voir tout de suite ce qu'elle fait, et un programme s'arrête à l'endroit exact où il rencontre un problème, en vous disant lequel.
Retenez cette double fonction: elle explique pourquoi certaines erreurs apparaissent avant que la moindre ligne ne s'exécute (l'interpréteur n'a pas su lire votre texte) et pourquoi d'autres apparaissent après que la moitié du programme a déjà tourné (il a su le lire, mais l'exécution a buté sur quelque chose d'impossible). Nous reviendrons longuement sur cette distinction.
Deux façons de parler à Python
Il y a deux manières de donner des instructions à l'interpréteur, et il faut se servir des deux.
La première est l'invite interactive (interactive prompt, ou REPL, pour read–eval–print loop). Vous tapez python3 dans un terminal, et l'interpréteur affiche trois chevrons >>> qui signifient «j'attends une instruction». Vous en tapez une, vous appuyez sur Entrée, et l'interpréteur l'exécute puis affiche le résultat s'il y en a un. C'est un brouillon de calcul: idéal pour essayer, vérifier une syntaxe, se rappeler ce que fait une opération. Rien n'y est conservé quand vous quittez.
La seconde est le script: un fichier texte dont le nom se termine par .py et qui contient une suite d'instructions. Vous l'écrivez dans un éditeur, vous l'enregistrez, puis vous le lancez depuis le terminal avec python3 mon_fichier.py. L'interpréteur exécute alors toutes les instructions du fichier, de la première à la dernière, et rend la main. C'est la forme définitive de tout programme: c'est elle qu'on relit, qu'on corrige et qu'on donne à quelqu'un d'autre.
Écrire et lancer un script
Ouvrez un éditeur de texte, écrivez les lignes suivantes, enregistrez le fichier sous le nom aire.py, puis, dans un terminal placé dans le même dossier, tapez python3 aire.py.
# aire.py : calcule l'aire d'un disque de rayon fixé
rayon = 2.5
aire = 3.14159 * rayon ** 2
print("Rayon:", rayon)
print("Aire:", aire)
Rayon: 2.5
Aire: 19.6349375
La première ligne commence par un croisillon #: c'est un commentaire. Tout ce qui suit un # jusqu'à la fin de la ligne est ignoré par l'interpréteur. Les commentaires ne servent qu'aux lecteurs humains, vous compris dans trois semaines. Un bon commentaire n'explique pas ce que fait la ligne (cela se lit) mais pourquoi elle est là.
Vous écrivez un fichier script.py qui contient une seule ligne: 3 + 4. Vous le lancez avec python3 script.py. Qu'affiche le terminal?
Variables et affectation
Le problème
Reprenons le programme précédent. Si le rayon change, il faut modifier la ligne de calcul; s'il apparaissait à cinq endroits, il faudrait le modifier cinq fois, et l'expérience montre qu'on en oublie toujours un. Plus fondamentalement, un programme qui ne sait que manipuler des nombres écrits en toutes lettres ne sert à rien: on veut calculer avec des grandeurs dont la valeur n'est pas connue au moment où l'on écrit. C'est à cela que servent les variables.
L'affectation
L'ordre «d'abord la droite, ensuite la gauche» est la clé de tout ce qui suit; relisez-le. Dans aire = 3.14159 * rayon ** 2, Python cherche la valeur actuelle de rayon, effectue la multiplication, obtient 19.6349375, et c'est seulement ensuite qu'il donne le nom aire à ce résultat.
L'image juste n'est pas celle d'une boîte dans laquelle on rangerait une valeur, mais celle d'une étiquette que l'on colle sur une valeur. La valeur vit en mémoire; le nom est une poignée qui permet d'y accéder. C'est une image que nous garderons jusqu'au bout du cours, parce qu'elle deviendra indispensable au chapitre 6 lorsque deux noms différents pourront désigner la même valeur.
Réaffecter
Une variable varie: on peut lui donner une nouvelle valeur autant de fois qu'on veut, et la nouvelle remplace purement et simplement l'ancienne.
note = 4.5
print(note)
note = 5.0
print(note)
note = "excellent"
print(note)
print(type(note))
4.5
5.0
excellent
<class 'str'>
Remarquez au passage que rien n'oblige la nouvelle valeur à être de même nature que l'ancienne: note a d'abord désigné un nombre, puis du texte. Python le permet, ce qui est commode et dangereux. Commode, parce qu'on n'a jamais à déclarer d'avance ce qu'une variable contiendra. Dangereux, parce que rien ne vous avertira: si note désigne tantôt un nombre tantôt du texte, la ligne note * 2 ne veut plus dire la même chose selon l'endroit du programme où on la lit, et la plupart des TypeError que nous décortiquerons à la fin de ce chapitre naissent exactement ainsi. Prenez donc dès maintenant l'habitude suivante: une variable garde le même genre de contenu d'un bout à l'autre du programme; quand vous avez besoin d'autre chose, prenez un autre nom.
Un exemple qui se passe mal si l'on va trop vite
Nommer
Python impose quelques règles, et l'usage en ajoute d'autres qui ne sont pas facultatives pour autant.
Les règles du langage: un nom est composé de lettres, de chiffres et du caractère de soulignement _; il ne peut pas commencer par un chiffre; il ne peut pas être l'un des trente-cinq mots réservés du langage (if, else, for, while, def, return, class, and, or, not, in, is, True, False, None, import…), que Python se garde pour lui. Les majuscules comptent: note et Note sont deux variables différentes.
Voici ce que l'interpréteur répond quand on enfreint ces règles. Le premier cas utilise un mot réservé, le second commence par un chiffre, le troisième contient un tiret — que Python lit comme une soustraction.
File "essai.py", line 1
class = 5
^
SyntaxError: invalid syntax
File "essai.py", line 1
2eme_note = 4.5
^
SyntaxError: invalid decimal literal
Les conventions, ensuite, qui sont ce que votre enseignant et vos collègues attendent:
- les noms de variables s'écrivent en
snake_case: tout en minuscules, les mots séparés par des soulignements, commenote_max,prix_hors_taxe,nombre_d_etudiants; - pas d'accents ni de cédilles, bien que Python les accepte techniquement —
prénom = "Alice"fonctionne. On s'en passe parce qu'un nom accentué se retape mal, se cherche mal, et se casse dès qu'un fichier change d'encodage. Ce cours écrit doncprenom,moyenne_ponderee,duree_ecoulee; - des noms français, entiers, et qui disent ce que la variable contient.
Parmi ces quatre noms de variables, lequel Python refuse-t-il?
Retenez le critère pratique pour les mots réservés: si votre éditeur colore un mot comme il colore if ou return, c'est un mot réservé et il vous faut en choisir un autre. Et retenez la différence entre les deux dernières options de la question: 2eme_note est interdit par le langage, moyenneMax est seulement déconseillé par l'usage. Les deux sont à corriger, mais seul le premier vous arrêtera.
Les types de base
Pourquoi les valeurs ont un type
Additionner deux nombres, coller deux morceaux de texte bout à bout et vérifier si deux affirmations sont vraies en même temps sont trois opérations différentes. Pour savoir laquelle appliquer, l'interpréteur doit connaître la nature de chaque valeur. Cette nature s'appelle son type.
Quatre types suffisent pour tout ce chapitre. Les trois autres grandes familles — les chaînes vues en détail au chapitre 5, les listes du chapitre 6 et les dictionnaires du chapitre 7 — viendront ensuite.
int(integer), les entiers:0,42,-7,1000000. Ils sont exacts et sans limite de taille: Python calcule sans se plaindre ni perdre un chiffre. Ils servent à compter — des objets, des tours de boucle, des centimes.float(floating point), les nombres à virgule flottante:4.5,-0.001,3.14159. Attention, le séparateur décimal en Python est le point, jamais la virgule: on écrit4.5dans le code, même si l'on écrit 4,5 dans le texte français. Ils servent à mesurer. Ils sont approchés, et la dernière section de ce chapitre est entièrement consacrée aux conséquences de ce fait.str(string), les chaînes de caractères: du texte, entre guillemets simples ou doubles,"Alice"ou'Alice'. Les deux écritures sont équivalentes; ce cours utilise les guillemets doubles. Une chaîne peut contenir des chiffres —"42"est du texte, pas un nombre, et cette distinction est à l'origine d'une bonne moitié des erreurs des premières semaines.bool(boolean), les booléens: exactement deux valeurs,TrueetFalse, avec une majuscule et sans guillemets. Elles représentent le résultat d'une question. Le chapitre 2 leur est consacré.
Interroger le type
>>> type(3)
<class 'int'>
>>> type(3.0)
<class 'float'>
>>> type("3")
<class 'str'>
>>> type(True)
<class 'bool'>
>>> type(3 / 1)
<class 'float'>
Le mot class de la réponse est un synonyme de «type» en Python; nous n'aurons pas besoin d'en savoir plus. Les trois premières lignes montrent que 3, 3.0 et "3" sont trois valeurs différentes, malgré leur apparence: un entier, un nombre à virgule et du texte. La dernière ligne est la plus instructive: 3 / 1 vaut trois, mais la division / produit toujours un float, même quand le résultat tombe juste. Nous y revenons dans un instant.
Quel est le type de la valeur désignée par prix après les deux lignes: prix = 20 puis prix = prix / 4?
Les opérateurs
Les opérateurs arithmétiques
Un opérateur combine une ou deux valeurs, appelées opérandes, pour en produire une nouvelle. Python en possède sept pour l'arithmétique.
| Opérateur | Nom | Exemple | Résultat |
|---|---|---|---|
+ | addition | 7 + 2 | 9 |
- | soustraction | 7 - 2 | 5 |
* | multiplication | 7 * 2 | 14 |
/ | division exacte | 7 / 2 | 3.5 |
// | division entière | 7 // 2 | 3 |
% | reste (modulo) | 7 % 2 | 1 |
** | puissance | 7 ** 2 | 49 |
Les quatre premiers ne surprennent personne. Les trois derniers méritent qu'on s'y arrête, car ce sont eux que l'on utilise sans les connaître.
Les deux divisions
/ est la division que vous connaissez: elle donne le quotient exact, sous forme de float, toujours, même quand la division tombe juste.
// est la division entière: elle donne le nombre de fois que le diviseur tient dans le dividende, en jetant ce qui dépasse. % donne précisément ce qui dépasse, c'est-à-dire le reste. Les deux vont ensemble et ce sont les opérations de la division euclidienne apprise à l'école primaire: pour tout entier et tout entier non nul,
>>> 17 // 5
3
>>> 17 % 5
2
>>> 17 / 5
3.4
On a bien . La division entière est l'outil de toutes les conversions d'unités, et le reste celui de toutes les questions de divisibilité et de cycles.
La priorité des opérateurs
Comme en mathématiques, les opérateurs ne s'appliquent pas de gauche à droite mais selon une priorité. De la plus forte à la plus faible:
| Priorité | Opérateurs | Sens |
|---|---|---|
| 1 (la plus forte) | ** | de droite à gauche |
| 2 | -x (moins unaire) | — |
| 3 | *, /, //, % | de gauche à droite |
| 4 | +, - | de gauche à droite |
| 5 (la plus faible) | ==, !=, <, > et leurs variantes | — |
>>> 3 + 4 * 2 ** 2
19
>>> (3 + 4) * 2 ** 2
28
>>> 10 - 3 - 2
5
>>> 2 ** 3 ** 2
512
La première ligne se lit . La troisième montre que - s'associe de gauche à droite: , et non . La quatrième montre que , lui, s'associe de : , et non .
Les opérateurs sur les chaînes
Deux opérateurs arithmétiques fonctionnent aussi sur le texte, avec un tout autre sens.
+ entre deux chaînes les concatène, c'est-à-dire les met bout à bout, sans rien ajouter entre elles. * entre une chaîne et un entier répète la chaîne.
>>> "bon" + "jour"
'bonjour'
>>> "-" * 20
'--------------------'
>>> "3" + "4"
'34'
>>> "5" * 3
'555'
>>> "Python" * 2 + "!"
'PythonPython!'
La ligne "3" + "4" mérite un arrêt: le résultat est '34' et non 7. Ce sont des chaînes; + les colle. La ligne "5" * 3 donne '555' et non 15. Si vous voulez additionner, il faut d'abord convertir, ce que nous ferons à la section suivante.
Les autres opérateurs n'ont aucun sens sur du texte et Python le dit franchement. Mélanger les deux mondes non plus:
age = "20"
print(age + 1)
Traceback (most recent call last):
File "essai.py", line 2, in <module>
print(age + 1)
~~~~^~~
TypeError: can only concatenate str (not "int") to str
Nous décortiquerons ce message à la fin du chapitre. Retenez pour l'instant sa traduction: «je ne sais concaténer à une chaîne qu'une autre chaîne, or on me donne un entier».
Les opérateurs de comparaison
Les six opérateurs de comparaison posent une question et répondent par un booléen.
| Opérateur | Question |
|---|---|
== | les deux valeurs sont-elles égales? |
!= | sont-elles différentes? |
< | la première est-elle strictement plus petite? |
> | la première est-elle strictement plus grande? |
<= | plus petite ou égale? |
>= | plus grande ou égale? |
>>> 3 < 5
True
>>> 3 == 3.0
True
>>> "abc" == "ABC"
False
>>> 4.5 >= 4
True
>>> type(3 < 5)
<class 'bool'>
Deux remarques. D'abord 3 == 3.0 est True: un int et un float de même valeur sont égaux, même si leurs types diffèrent. Ensuite la comparaison de chaînes est sensible à la casse: "abc" et "ABC" sont deux textes différents.
Ces opérateurs ne servent à rien tant qu'on ne sait pas s'en servir pour décider quelque chose; c'est l'objet du chapitre 2. Mais il faut les connaître dès maintenant, parce que == est le compagnon obligé de = dans la tête d'un débutant.
L'explorateur d'expressions
L'explorateur ci-dessous évalue a op b pour les opérandes et l'opérateur que vous choisissez, et affiche le résultat et son type. Faites-y trois expériences avant de continuer: avec a = 7 et b = 2, comparez / et //; passez le type des opérandes à «chaîne · chaîne» et regardez ce que devient +; puis, toujours en chaînes, essayez - et lisez le message d'erreur, qui est exactement celui que Python produirait.
Choisissez deux opérandes, un opérateur et le type des opérandes: l'explorateur affiche la valeur du résultat et son type. Les valeurs, les types et les messages d'erreur sont ceux de Python 3.13, reproduits à l'identique.
Le bandeau du bas est la leçon du chapitre: quels que soient les opérandes, les deux divisions donnent deux valeurs et deux types différents, et cette différence ne disparaît jamais.
Que vaut l'expression , c'est-à-dire, en Python, 17 // 5 + 17 % 5?
Les conversions de type
Convertir explicitement
Trois fonctions natives transforment une valeur d'un type en une valeur d'un autre type. Elles ne modifient jamais la valeur qu'on leur donne: elles en fabriquent une nouvelle.
int(x)construit un entier. À partir d'unfloat, elle tronque vers zéro:int(3.9)vaut3etint(-3.9)vaut-3— ce n'est pas un arrondi, et ce n'est pas non plus le comportement de//. À partir d'une chaîne, elle lit un nombre écrit en chiffres.float(x)construit un nombre à virgule:float(7)vaut7.0,float("4.5")vaut4.5.str(x)construit le texte qui représente la valeur:str(42)vaut"42". C'est ce qu'il faut quand on veut concaténer un nombre à une phrase.
>>> int("42")
42
>>> float("4.5")
4.5
>>> str(42)
'42'
>>> int(3.9)
3
>>> int(-3.9)
-3
>>> float(7)
7.0
Pour arrondir plutôt que tronquer, il existe round(): round(3.9) vaut 4. Sachez dès maintenant que round applique l'arrondi dit «au pair le plus proche» pour les cas d'égalité — round(2.5) vaut 2 et round(3.5) vaut 4 — ce qui est la règle recommandée en métrologie, et ce qui surprend tout le monde la première fois.
Quand la conversion échoue
int() ne devine rien. Elle accepte une chaîne qui contient exactement un entier écrit en chiffres, éventuellement entouré d'espaces, et refuse tout le reste — y compris un nombre à virgule, y compris la virgule française.
texte = "douze"
nombre = int(texte)
print(nombre)
Traceback (most recent call last):
File "essai.py", line 2, in <module>
nombre = int(texte)
ValueError: invalid literal for int() with base 10: 'douze'
Les deux refus suivants sont encore plus fréquents dans les copies d'étudiants:
nombre = int("4.5")
Traceback (most recent call last):
File "essai.py", line 1, in <module>
nombre = int("4.5")
ValueError: invalid literal for int() with base 10: '4.5'
nombre = float("4,5")
Traceback (most recent call last):
File "essai.py", line 1, in <module>
nombre = float("4,5")
ValueError: could not convert string to float: '4,5'
Le premier échoue parce que "4.5" n'est pas un entier: il faut écrire int(float("4.5")), qui vaut 4. Le second échoue parce que Python ne connaît que le point décimal: une saisie française avec une virgule doit être corrigée avant conversion. Retenez la formule de ces messages, invalid literal et could not convert: elles signalent toujours une valeur que la fonction n'a pas su lire, jamais une faute de frappe dans votre programme.
Que vaut int(float('7.9'))?
Entrées et sorties
Un programme qui ne communique pas avec l'extérieur ne sert à rien. Les deux fonctions natives print() et input() assurent le minimum: afficher à l'écran, lire au clavier.
Afficher avec print()
print() accepte plusieurs arguments, séparés par des virgules, les affiche les uns après les autres séparés par une espace, puis passe à la ligne. Les arguments peuvent être de n'importe quel type et sont convertis en texte automatiquement pour l'affichage — c'est le seul endroit où la conversion est implicite.
Deux paramètres nommés permettent de modifier ce comportement. sep remplace l'espace qui sépare les arguments; end remplace le passage à la ligne final.
print("Rayon", 2.5, "cm")
print("a", "b", "c", sep="-")
print("Total", 54.0, sep=": ")
print("sans retour", end=" | ")
print("à la ligne")
print()
print
Rayon 2.5 cm
a-b-c
Total: 54.0
sans retour | à la ligne
après une ligne vide
Détaillez la quatrième et la cinquième ligne: la quatrième s'est terminée par " | " au lieu d'un passage à la ligne, la cinquième a donc écrit à la suite sur la même ligne. Et print() sans aucun argument produit simplement une ligne vide, ce qui est la façon normale d'aérer une sortie.
Les virgules de print évitent d'avoir à convertir soi-même: print("Aire:", aire) fonctionne quel que soit le type de aire, alors que print("Aire: " + aire) échouerait si aire était un nombre. Le chapitre 5 introduira une troisième façon d'écrire, plus souple, mais les virgules suffisent largement jusque-là.
Lire au clavier avec input()
input() affiche le texte qu'on lui donne, attend que l'utilisateur tape une ligne et appuie sur Entrée, puis renvoie cette ligne. Dans les transcriptions ci-dessous, ce qui apparaît après le message d'invite est ce que l'utilisateur a tapé.
prenom = input("Votre prénom: ")
print("Bonjour", prenom)
Votre prénom: Alice
Bonjour Alice
Remettez dans l'ordre les quatre lignes d'un programme qui demande une température en degrés Celsius et affiche son équivalent en degrés Fahrenheit.
Glissez les éléments pour les mettre dans le bon ordre
- fahrenheit = celsius * 9 / 5 + 32
- print(celsius, "°C font", fahrenheit, "°F")
- texte = input("Température en °C: ")
- celsius = float(texte)
Les flottants ne sont pas les réels
Le fait
Voici la ligne la plus importante du chapitre.
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False
Ce n'est pas un bogue de Python. Tous les langages qui utilisent les nombres à virgule flottante de la norme IEEE 754 — c'est-à-dire tous ceux que vous rencontrerez — donnent exactement ce résultat, y compris le tableur qui vous le cache en n'affichant que quinze chiffres.
L'explication
La mémoire d'un ordinateur ne connaît que le binaire. Un float est stocké sur 64 bits, dont 53 servent à écrire les chiffres significatifs en base 2. Or un nombre s'écrit avec un nombre fini de chiffres en base 2 seulement si son dénominateur est une puissance de deux. C'est le même phénomène qu'en base 10, où s'écrit sans jamais se terminer: en base 2, est un développement infini périodique, exactement comme en base 10.
Puisqu'on ne peut pas garder une infinité de chiffres, la machine garde les 53 premiers et arrondit. La valeur réellement stockée quand vous écrivez 0.1 n'est donc pas un dixième, mais le nombre représentable le plus proche:
>>> format(0.1, ".20f")
'0.10000000000000000555'
Python vous cache cette différence à l'affichage, en imprimant le plus court texte qui permette de retrouver exactement la même valeur binaire — d'où 0.1 à l'écran. Mais l'écart est là, et lorsqu'on additionne 0.1 et 0.2, les deux écarts s'additionnent aussi et deviennent visibles au seizième chiffre.
Tous les nombres ne sont pas concernés: 0.5, 0.25, 0.75 sont des fractions de puissance de deux et sont stockés exactement. 0.5 + 0.25 == 0.75 vaut True. Le problème ne se voit donc jamais quand on l'essaie sur les «bons» nombres, ce qui le rend d'autant plus traître.
Trois articles coûtent chacun 0,10 franc. On calcule le total avec 0.1 * 3 puis on le compare à 0.3 avec l'opérateur ==. Combien de centimes vaut réellement l'écart, une fois le total arrondi au centime avec round(total, 2)?
Ne croyez personne sur parole, pas même ce cours: exécutez-le. Puis remplacez la comparaison de la dernière ligne par une comparaison à tolérance, pour que le programme affiche False puis True.
Lire une erreur
Une erreur n'est pas un échec
Vous allez voir des centaines de messages d'erreur. Ce ne sont pas des punitions mais des diagnostics, souvent d'une précision remarquable, et apprendre à les lire est une compétence en soi — la plus rentable des premières semaines. Le réflexe à combattre est de refermer le terminal en soupirant; le réflexe à acquérir est de lire la dernière ligne d'abord, puis de remonter.
Python appelle trace d'appels (traceback) le bloc de texte qu'il affiche quand un programme s'interrompt. Voici un exemple réel: un fichier aire.py dont l'auteur a écrit rayon alors qu'il avait nommé sa variable diametre.
Cinq éléments, toujours les mêmes:
- L'en-tête
Traceback (most recent call last):annonce qu'une erreur a interrompu l'exécution. Il ne contient aucune information utile; ignorez-le. - Le fichier, entre guillemets, vous dit dans lequel de vos fichiers l'erreur s'est produite. Dans ce chapitre il n'y en a qu'un; à partir du chapitre 8 il y en aura plusieurs.
- Le numéro de ligne vous dit où exactement. Votre éditeur sait vous y emmener.
- La ligne de code, recopiée telle quelle, avec en dessous des accents circonflexes
^sous la partie fautive. Cette indication précise est apparue avec Python 3.11 et vaut de l'or: elle désigne le morceau exact de l'expression que l'interpréteur n'a pas pu évaluer. - Le type de l'erreur, suivi de deux-points et du message. C'est la ligne à lire en premier.
Nous abrégeons dans tout ce chapitre le chemin complet que Python affiche — sur votre machine, quelque chose comme /home/vous/python/aire.py — en son seul nom de fichier. C'est la seule retouche faite aux messages reproduits ici; tout le reste est exactement ce que Python a imprimé.
Les quatre erreurs du premier mois
Quatre types d'erreurs couvrent l'essentiel de ce que vous verrez dans ce chapitre. Chacune a une cause caractéristique.
SyntaxError: Python n'a pas su lire votre texte. C'est la seule des quatre qui se produit avant toute exécution: rien du programme n'a tourné, pas même la première ligne. Le message est souvent laconique et le curseur ^ pointe l'endroit où l'interpréteur a perdu le fil — qui est parfois après la vraie faute, typiquement une parenthèse ou un guillemet jamais refermés à la ligne précédente.
message = "bonjour
print(message)
File "essai.py", line 1
message = "bonjour
^
SyntaxError: unterminated string literal (detected at line 1)
Traduction: «chaîne de caractères non terminée». Le guillemet ouvrant n'a pas de guillemet fermant. Remarquez que l'en-tête Traceback est absent: il n'y a pas eu d'exécution, donc rien à retracer.
NameError: vous utilisez un nom qui n'existe pas. Presque toujours une faute de frappe, ou une variable utilisée avant d'avoir été affectée.
rayon = 2.5
aire = 3.14159 * raton ** 2
print(aire)
Traceback (most recent call last):
File "essai.py", line 2, in <module>
aire = 3.14159 * raton ** 2
^^^^^
NameError: name 'raton' is not defined. Did you mean: 'rayon'?
Python va jusqu'à proposer le nom qui ressemble le plus. La question Did you mean: est une suggestion, pas un diagnostic: elle a souvent raison et parfois tort.
TypeError: l'opération n'a pas de sens pour ces types-là. C'est l'erreur du texte qu'on prend pour un nombre.
age = "20"
print(age + 1)
Traceback (most recent call last):
File "essai.py", line 2, in <module>
print(age + 1)
~~~~^~~
TypeError: can only concatenate str (not "int") to str
Les tildes ~ soulignent les opérandes et le ^ l'opérateur en cause. La correction est print(int(age) + 1), ou mieux, convertir age dès sa création.
ValueError: le type est bon mais la valeur est inacceptable. C'est l'erreur de la conversion impossible.
texte = "douze"
nombre = int(texte)
print(nombre)
Traceback (most recent call last):
File "essai.py", line 2, in <module>
nombre = int(texte)
ValueError: invalid literal for int() with base 10: 'douze'
La distinction entre les deux dernières est subtile et vaut la peine d'être comprise: int() accepte parfaitement qu'on lui donne une chaîne — c'est son travail — donc ce n'est pas une erreur de type; mais cette chaîne-là ne contient pas de nombre, donc c'est une erreur de valeur.
Un premier programme complet
Construisons maintenant, ligne par ligne, un programme qui demande un rayon à l'utilisateur et affiche l'aire du disque correspondant. Il ne fait rien d'extraordinaire, mais il contient déjà tout ce que ce chapitre a introduit, et sa structure — lire, convertir, calculer, afficher — est celle de la plupart des programmes que vous écrirez avant le chapitre 3.
Synthèse
- Un programme est une suite d'instructions exécutées dans l'ordre par un interpréteur, qui joue à la fois le rôle de correcteur (il refuse ce qu'il ne sait pas lire) et d'exécutant (il fait exactement ce qui est écrit). On l'utilise à l'invite
>>>pour essayer, et par fichier.pypour construire; l'affichage automatique des résultats n'existe qu'à l'invite. - L'affectation
nom = expressionévalue d'abord la droite, puis attache le nom au résultat. Un nom est une étiquette collée sur une valeur, pas une boîte; réaffecter déplace l'étiquette et abandonne l'ancienne valeur.=donne un ordre,==pose une question:x = x + 1n'a de sens que dans le premier monde. - Les quatre types de base sont
int(exact, sans limite),float(approché),str(du texte, même quand il ne contient que des chiffres) etbool(TrueouFalse).type()les révèle,int(),float()etstr()convertissent, et une conversion impossible lève uneValueError. /produit toujours unfloat;//donne le quotient entier arrondi vers le bas et%le reste, liés par . Sur les chaînes, concatène et répète. a la priorité la plus forte et s'associe de droite à gauche, si bien que vaut .
Après les deux instructions a = 3 puis b = a, on exécute a = 10. Que vaut b?
Exercices
Vous pouvez afficher le corrigé directement sous chaque énoncé après avoir cherché la solution.
Un ordinateur portable coûte 1290 francs. Écrivez un programme qui:
- range ce prix dans une variable
prix; - lui applique une remise de 15 %, en réaffectant
prix; - y ajoute 39,90 francs de garantie, toujours en réaffectant
prix; - affiche le prix remisé, le prix avec garantie, puis le prix arrondi au franc.
Prédisez les trois valeurs avant de lancer le programme.
Solution
prix = 1290.0
remise = 0.15
prix = prix - prix * remise
print("Prix remisé:", prix)
prix = prix +
Sans lancer Python, dites ce qu'affichent les six expressions suivantes, avec leur type: 17 / 4, 17 // 4, 17 % 4, -17 // 4, -17 % 4, 17.0 // 4. Vérifiez ensuite vos réponses à l'invite interactive, puis expliquez en une phrase la différence entre les deux dernières et les deux précédentes.
Solution
>>> 17 / 4
4.25
>>> 17 // 4
4
>>> 17 % 4
1
>>> -17 // 4
-5
>>> -17 % 4
3
>>> 17.0 // 4
4.0
Les types sont, dans l'ordre: float, int, int, int, int, float.
17 / 4 donne le quotient exact, toujours flottant. 17 // 4 donne 4 et 17 % 4 donne 1, avec .
Les cas négatifs sont ceux qui surprennent. // arrondit vers le bas, c'est-à-dire vers , et non vers zéro: , et l'entier immédiatement inférieur est . Le reste s'ajuste pour que la relation de la division euclidienne reste vraie: , donc vaut 3. En Python, le reste a toujours le signe du diviseur, ce qui est commode: un reste modulo 4 est toujours 0, 1, 2 ou 3, même pour des nombres négatifs.
Écrivez un programme qui demande deux nombres à l'utilisateur, puis affiche leur somme, leur différence, leur quotient exact, leur quotient entier et leur reste. Lancez-le avec 7 et 2. Que se passerait-il si vous aviez oublié la conversion?
Solution
a = float(input("Premier nombre: "))
b = float(input("Deuxième nombre: "))
print("Somme:", a + b)
print("Différence:", a - b)
Pour chacune des quatre traces ci-dessous, dites: à quelle ligne du programme l'erreur se produit, quel type d'erreur c'est, quelle en est la cause réelle, et quelle correction vous proposez. Attention: dans un cas, la cause n'est pas à la ligne indiquée.
(a)
File "a.py", line 3
print("resultat : , total)
^
SyntaxError: unterminated string literal (detected at line 3)
(b)
Traceback (most recent call last):
File "b.py", line 2, in <module>
surface = longeur * largeur
^^^^^^^
NameError: name 'longeur' is not defined. Did you mean: 'longueur'?
(c)
Traceback (most recent call last):
File "c.py", line 4, in <module>
total = prix * quantite
~~~~~^~~~~~~~~~
TypeError: can't multiply sequence by non-int of type 'str'
(d)
Traceback (most recent call last):
File "d.py", line 1, in <module>
n = int(input("Un entier: "))
ValueError: invalid literal for int() with base 10: '3.5'
Solution
(a) Ligne 3, SyntaxError. Un guillemet fermant manque après resultat : , si bien que Python lit , total) comme faisant partie de la chaîne et arrive à la fin de la ligne sans l'avoir vue se terminer. Le ^ désigne le guillemet ouvrant, c'est-à-dire le début de la chaîne qui n'a jamais été refermée, et non l'endroit où l'on aurait voulu la fermer. Correction: print("resultat :", total). Remarquez l'absence d'en-tête Traceback: le programme n'a jamais commencé à s'exécuter, donc les lignes 1 et 2 n'ont rien fait non plus.
(b) Ligne 2, NameError, provoquée par une faute de frappe: la variable a été créée sous le nom longueur et utilisée sous le nom longeur. Python le devine et le dit. Correction: rétablir l'orthographe à la ligne 2. C'est le cas où la suggestion Did you mean est fiable, parce que les deux noms ne diffèrent que d'une lettre.
(c) Ligne 4, TypeError. Le message est celui de la répétition d'une chaîne: prix est une chaîne, et l'on tente de la multiplier par autre chose qu'un entier, donc est une chaîne aussi. La cause réelle n'est pas à la ligne 4 mais , là où et ont été lus avec sans conversion. Correction: et au moment de la lecture. C'est le cas annoncé dans l'énoncé: la ligne indiquée est celle où l'erreur , pas celle où elle a été .
Un commerçant vend un article 0,10 franc. Un client en prend trois.
- Écrivez un programme qui calcule le total avec des
float, l'affiche, et affiche le résultat du test d'égalité entre ce total et0.3. - Ajoutez un test correct, à une tolérance de , et affichez aussi le total arrondi au centime.
- Récrivez le même calcul entièrement en centimes entiers et comparez.
- Expliquez laquelle des deux versions vous utiliseriez dans une caisse enregistreuse, et pourquoi.
Solution
1 et 2.
prix_unitaire = 0.1
quantite = 3
total = prix_unitaire * quantite
attendu
Références
- Downey, A., Think Python, 3e éd., O'Reilly, Sebastopol, chapitres 1 et 2 (variables, expressions et instructions). Librement disponible en ligne, traduction française existante.
- Swinnen, G., Apprendre à programmer avec Python 3, Eyrolles, Paris, chapitres 1 et 2 (premiers pas, variables et types). Librement disponible en ligne.
- Matthes, E., Python Crash Course, 3e éd., No Starch Press, San Francisco, chapitre 2 (variables et types simples).
- Guttag, J. V., Introduction to Computation and Programming Using Python, 3e éd., MIT Press, Cambridge, chapitre 2 (introduction à Python).
- La documentation officielle Python, docs.python.org, section «Types intégrés», sous-sections «Types numériques» et «Types de séquences de texte».
- Le tutoriel officiel Python, docs.python.org, section «Utiliser Python comme une calculatrice» et section «Erreurs et exceptions».