← Parcours

Introduction à la programmation

DébutantJavaScriptPythonBases

Apprends à penser comme un programme : variables, conditions, boucles, fonctions, listes et dictionnaires, avec des exercices en JavaScript et en Python. Aucun prérequis, et un petit magasin à construire du début à la fin.

1. Bienvenue : comment ce cours fonctionne

Objectif : à la fin de ce chapitre, tu sais comment suivre ce cours pour retenir un maximum, et tu sais où écrire et lancer ton premier code.

Ce que tu sauras faire à la fin du cours

À la fin de ces dix chapitres, tu sauras écrire seul·e de petits programmes complets : ils prennent des données, prennent des décisions, répètent des tâches, et affichent un résultat. Tu les écriras en JavaScript et en Python, deux des langages les plus utilisés au monde.

Pourquoi deux langages ? Parce que les idées sont les mêmes partout : une variable, une condition, une boucle, une fonction. Seule la façon de les écrire change. Tu peux suivre le cours avec un seul des deux langages. Mais si tu lis les deux versions, tu comprendras vite que tu n'apprends pas « du JavaScript » ou « du Python » : tu apprends à programmer.

Le fil rouge : un petit magasin

Pour que ce soit concret, tu construiras pas à pas la caisse d'un petit magasin :

  • au chapitre 3, tu calcules le prix d'un article ;
  • au chapitre 4, tu appliques une remise ;
  • au chapitre 5, tu totalises plusieurs articles ;
  • au chapitre 6, tu ranges ces calculs dans des fonctions ;
  • aux chapitres 7 et 8, tu stockes le panier et le catalogue ;
  • au chapitre 10, tu assembles tout pour afficher un vrai ticket de caisse.

Comment chaque chapitre est construit

Chaque chapitre explique une seule idée et suit toujours le même parcours :

  1. L'idée : l'explication, courte.
  2. Un exemple pas à pas : un programme complet, expliqué ligne par ligne.
  3. À retenir : un résumé que tu pourras relire plus tard.
  4. Quiz : quelques questions pour vérifier que tu as compris.
  5. Code à corriger : un programme qui contient un bug, à toi de le trouver.
  6. Exercice : un petit programme à écrire toi-même.
  7. Corrigés : les réponses, avec le pourquoi.

La règle d'or : cherche avant de regarder

Il est tentant de lire directement les corrigés. Ne le fais pas : c'est en essayant de te souvenir, et même en te trompant, que le cerveau retient le mieux. Relire une explication donne l'impression de savoir ; chercher la réponse, lui, fait vraiment apprendre.

Voici donc comment travailler :

  • Réponds au quiz avant de lire les corrigés, même si tu hésites. Une mauvaise réponse suivie de la bonne explication t'apprend plus qu'une bonne réponse devinée.
  • Tape le code toi-même au lieu de le copier. Tes doigts retiennent la syntaxe.
  • Les erreurs sont normales. Même les développeurs expérimentés passent leur journée à lire des messages d'erreur.
  • Reviens le lendemain. Revoir une notion après une nuit de sommeil la fixe bien mieux que de tout faire d'un coup. Les premières questions de chaque quiz te feront d'ailleurs revenir sur les chapitres précédents.
  • Compte 20 à 30 minutes par chapitre. Mieux vaut un chapitre par jour que trois d'un coup.

Où écrire et lancer ton code

Tu as besoin d'un endroit pour faire tourner tes programmes. Bientôt, SynAck te proposera un éditeur directement dans la page. En attendant :

  • JavaScript : ton navigateur sait déjà l'exécuter. Ouvre n'importe quelle page, appuie sur la touche F12, choisis l'onglet Console, tape une ligne, puis Entrée.
  • Python : installe-le depuis le site officiel python.org, puis, dans un terminal, tape python3 (ou python sous Windows) pour obtenir une console, ou lance un fichier avec python3 mon_programme.py.

Fais un essai maintenant : en JavaScript, tape 2 + 3 dans la console et vérifie que tu obtiens 5. En Python, tape 2 + 3 dans la console de Python : même résultat. Tu viens de faire tourner du code.

À retenir

  • Le cours suit un seul fil : un petit magasin, construit chapitre après chapitre.
  • Chaque chapitre = une idée, un exemple, un quiz, un bug à corriger, un exercice.
  • Cherche avant de regarder les corrigés : c'est ce qui fait retenir.
  • JavaScript et Python expriment les mêmes idées avec une écriture différente.

Quiz

Question 1. Quand dois-tu lire les corrigés d'un chapitre ?

  • A. Avant de faire le quiz, pour être sûr·e de ne pas te tromper.
  • B. Après avoir essayé de répondre toi-même, même en hésitant.
  • C. Jamais : ils ne servent à rien.

Question 2. Pourquoi est-il préférable de taper le code plutôt que de le copier ?

Corrigés

Question 1 : B. Se tromper puis lire la bonne explication fait mieux retenir que lire la réponse d'emblée. L'effort de chercher compte plus que de réussir du premier coup.

Question 2. Parce que taper le code te fait remarquer chaque détail (une parenthèse, un guillemet, une majuscule). Ces détails sont justement ce qui provoque les erreurs au début, et ce sont tes doigts, autant que ta tête, qui les retiennent.

2. Ton premier programme

Objectif : à la fin de ce chapitre, tu sais écrire un programme de plusieurs instructions qui affiche du texte dans le bon ordre, et tu sais lire le message d'erreur quand il refuse de démarrer.

L'idée

Un programme, c'est une liste d'instructions. L'ordinateur les exécute l'une après l'autre, de haut en bas, et fait exactement ce qu'on lui dit : ni plus, ni moins. Il ne devine rien et n'improvise jamais.

Pense à une recette de cuisine écrite pour quelqu'un qui n'a jamais cuisiné : si tu oublies une étape, ou si tu les écris dans le désordre, le gâteau est raté. Programmer, c'est écrire une recette sans ambiguïté.

La première instruction à connaître est celle qui affiche du texte à l'écran :

  • en JavaScript : console.log(...)
  • en Python : print(...)

Un exemple pas à pas

Voici un programme de trois instructions. Il affiche trois lignes, dans l'ordre :

JavaScript
console.log("Bonjour !");
console.log("Je m'appelle SynAck.");
console.log("Enchanté.");
Python
print("Bonjour !")
print("Je m'appelle SynAck.")
print("Enchanté.")

Résultat affiché, dans les deux langages :

Résultat
Bonjour !
Je m'appelle SynAck.
Enchanté.

Regardons une ligne de plus près :

  • console.log ou print est le nom de l'instruction ;
  • les parenthèses contiennent ce qu'on lui donne à afficher ;
  • le texte est entouré de guillemets : on appelle cela une chaîne de caractères ;
  • en JavaScript, on termine souvent la ligne par un point-virgule ;. En Python, on ne le met pas.

L'ordre compte. Si tu inverses les deux premières lignes, l'affichage s'inverse aussi : l'ordinateur suit ta liste, pas ton intention.

Les commentaires

Un commentaire est une phrase que l'ordinateur ignore, écrite pour les humains qui liront le code, y compris toi dans trois semaines :

JavaScript
// Cette ligne est ignorée par l'ordinateur
console.log("Salut"); // un commentaire peut aussi suivre une instruction
Python
# Cette ligne est ignorée par l'ordinateur
print("Salut")  # un commentaire peut aussi suivre une instruction

En JavaScript, un commentaire commence par //. En Python, par #.

Quand ça ne marche pas : lire une erreur

Tu vas faire des erreurs, tout le monde en fait. Ce qui compte, c'est de savoir lire le message. Oublie le guillemet fermant :

JavaScript
console.log("Bonjour);
Python
print("Bonjour)

L'ordinateur refuse de démarrer et t'écrit, en anglais, quelque chose comme :

Résultat
SyntaxError: Invalid or unexpected token          (JavaScript)
SyntaxError: unterminated string literal          (Python)

Un message d'erreur contient presque toujours trois informations utiles :

  1. le type de l'erreur (ici SyntaxError, une erreur d'écriture : le code ne respecte pas la grammaire du langage) ;
  2. une explication (ici : une chaîne de caractères n'est jamais refermée) ;
  3. la ligne concernée, souvent soulignée avec une flèche ^.

Un message d'erreur n'est pas un reproche : c'est un indice que l'ordinateur te donne gratuitement.

À retenir

  • Un programme est une liste d'instructions exécutées dans l'ordre, de haut en bas.
  • On affiche avec console.log(...) en JavaScript et print(...) en Python.
  • Le texte s'écrit entre guillemets.
  • Un commentaire (// en JavaScript, # en Python) est ignoré par l'ordinateur.
  • Un message d'erreur donne le type, l'explication et la ligne : lis-le avant de paniquer.

Quiz

Essaie de répondre sans relire le chapitre.

Question 1. Que fait un ordinateur quand il exécute un programme ?

  • A. Il devine ce que tu voulais écrire et corrige tout seul.
  • B. Il exécute les instructions l'une après l'autre, de haut en bas.
  • C. Il les exécute dans un ordre aléatoire.

Question 2. Qu'affiche ce programme ?

JavaScript
console.log("Bonjour");
// console.log("tout le monde");
console.log("à toi");
Python
print("Bonjour")
# print("tout le monde")
print("à toi")

Question 3. En une phrase : à quoi sert un commentaire ?

Code à corriger

Ce programme doit faire un compte à rebours, mais il affiche 3, 1, 2, puis Décollage !. Il y a un seul bug. Trouve-le et corrige-le.

JavaScript
console.log(3);
console.log(1);
console.log(2);
console.log("Décollage !");
Python
print(3)
print(1)
print(2)
print("Décollage !")

Exercice

Tu viens de rejoindre un club de programmation. Écris un programme qui affiche ta carte de visite en trois lignes : ton nom, ce que tu apprends, puis une ligne de séparation de 20 tirets. Par exemple :

Résultat
Ada Lovelace
Apprend la programmation
--------------------

Écris-le d'abord, puis seulement ensuite regarde le corrigé.

Corrigés

Quiz, question 1 : B. L'ordinateur suit ta liste à la lettre, du haut vers le bas. Il ne devine rien (A) et ne mélange pas les lignes (C).

Quiz, question 2. Le programme affiche deux lignes :

Résultat
Bonjour
à toi

La ligne du milieu est un commentaire : l'ordinateur l'ignore, donc tout le monde n'apparaît jamais.

Quiz, question 3. Un commentaire sert à expliquer le code aux humains (pourquoi on fait ça, ce que fait cette partie). L'ordinateur, lui, ne le lit pas.

Code à corriger. Le bug est un bug d'ordre : les instructions s'exécutent dans l'ordre où elles sont écrites, donc 1 passe avant 2 mais après 3. Il faut écrire 3, puis 2, puis 1 :

JavaScript
console.log(3);
console.log(2);
console.log(1);
console.log("Décollage !");
Python
print(3)
print(2)
print(1)
print("Décollage !")

Exercice. Une solution possible :

JavaScript
console.log("Ada Lovelace");
console.log("Apprend la programmation");
console.log("--------------------");
Python
print("Ada Lovelace")
print("Apprend la programmation")
print("--------------------")

Pour aller plus loin : change les trois lignes pour mettre ton nom et ce que tu apprends vraiment, puis ajoute une quatrième ligne avec ton adresse e-mail.

3. Les variables et les types

Objectif : à la fin de ce chapitre, tu sais ranger une valeur dans une variable, faire des calculs avec, et afficher une phrase construite à partir de tes variables.

L'idée

Un programme manipule des données : un prix, un nom, un âge. Pour les retrouver, on leur donne un nom. Une variable, c'est une étiquette collée sur une valeur.

On crée une variable avec le signe =, qu'on appelle une affectation :

  • en JavaScript : let prix = 12.5;
  • en Python : prix = 12.5

Attention : en programmation, = ne veut pas dire « égal » comme en mathématiques. Il veut dire : « range la valeur de droite dans le nom de gauche ». Une ligne comme prix = 12.5 se lit « prix prend la valeur 12,5 ».

Une variable peut changer de valeur au fil du programme, c'est même pour ça qu'elle s'appelle ainsi.

Les types de valeurs

Chaque valeur a un type. Les trois premiers à connaître :

  • un nombre : 3 (entier) ou 12.5 (décimal, avec un point et non une virgule) ;
  • un texte (une chaîne de caractères), entre guillemets : "Bonjour" ;
  • un booléen, qui vaut seulement vrai ou faux : true / false en JavaScript, True / False en Python. Tu t'en serviras dès le chapitre suivant.

Le type détermine ce qu'on a le droit de faire avec la valeur : on peut multiplier deux nombres, pas deux mots.

Choisir un bon nom

Un nom de variable contient des lettres, des chiffres et des tirets bas _. Il ne contient pas d'espace, ne commence pas par un chiffre, et les majuscules comptent (Prix et prix sont deux variables différentes).

Choisis des noms qui disent ce qu'il y a dedans : prix_total est bien meilleur que x. Par habitude, on écrit prixTotal en JavaScript (une majuscule à chaque mot) et prix_total en Python (des tirets bas). Dans ce cours, on garde des noms simples sans accent.

Un exemple pas à pas : le prix d'un article

Première pièce de ton petit magasin : calculer ce que coûtent 3 articles à 12,50 € l'unité.

JavaScript
let prix = 12.5;
let quantite = 3;
let total = prix * quantite;
console.log(`Total : ${total} €`);
Python
prix = 12.5
quantite = 3
total = prix * quantite
print(f"Total : {total} €")

Résultat :

Résultat
Total : 37.5 €

Ligne par ligne :

  1. prix reçoit 12.5 ;
  2. quantite reçoit 3 ;
  3. total reçoit le résultat de prix * quantite, c'est-à-dire 37.5 : l'ordinateur calcule d'abord le côté droit, puis range le résultat à gauche ;
  4. on affiche une phrase. Les ${total} (JavaScript, avec des accents graves autour du texte) et les {total} (Python, avec un f devant les guillemets) insèrent la valeur de la variable dans le texte.

Les opérations de base sont +, -, * (multiplier), / (diviser) et % (le reste de la division : 7 % 3 vaut 1).

Une variable garde une copie, pas un lien

Suis ce programme ligne par ligne avec un papier :

JavaScript
let a = 10;
let b = a;
a = a + 5;
console.log(a, b);
Python
a = 10
b = a
a = a + 5
print(a, b)

À la ligne 2, b reçoit la valeur de a (10), pas un lien vers a. Quand a change ensuite, b ne bouge pas. Le programme affiche 15 10.

Et a = a + 5 ? Ce n'est pas une équation impossible : c'est « calcule a + 5 avec la valeur actuelle de a, puis range le résultat dans a ». On s'en servira beaucoup.

Le piège des types

Que se passe-t-il quand on additionne un texte et un nombre ?

JavaScript
console.log("5" + 3);
Python
print("5" + 3)
  • JavaScript colle les deux et affiche le texte 53. Pas d'erreur, mais pas non plus ce que tu voulais peut-être !
  • Python refuse : TypeError: can only concatenate str (not "int") to str. Il te signale que tu mélanges deux types.

Quand une valeur est du texte alors que tu la voulais en nombre, convertis-la : Number("5") en JavaScript, int("5") en Python. Number("5") + 3 donne bien 8.

Dernier détail : les ordinateurs comptent en binaire et arrondissent parfois les décimales. Par exemple 0.1 + 0.2 donne 0.30000000000000004. Ce n'est pas un bug de ton programme. On en reparlera.

À retenir

  • Une variable est un nom collé sur une valeur ; = signifie « range à gauche la valeur calculée à droite ».
  • Les types de base : nombre, texte (entre guillemets), booléen.
  • Une variable garde une copie de la valeur : modifier a ne modifie pas b.
  • On insère une variable dans un texte avec ${...} (JavaScript) ou un f"...{...}..." (Python).
  • Mélanger texte et nombre est un piège : convertis avec Number(...) ou int(...).

Quiz

Question 1. Que valent a et b à la fin de ce programme ?

JavaScript
let a = 4;
let b = a * 2;
a = 1;
Python
a = 4
b = a * 2
a = 1

Question 2. Lequel de ces noms est un nom de variable valide (dans les deux langages) ?

  • A. 2prix
  • B. prix total
  • C. prix_total
  • D. prix-total

Question 3. Rappel du chapitre précédent : dans quel ordre l'ordinateur exécute-t-il les instructions d'un programme ?

Question 4. Qu'affiche ce code JavaScript ? Que se passerait-il avec le même code en Python ?

JavaScript
let age = "12";
console.log(age + 1);

Code à corriger

Le programme du magasin doit afficher Total : 37.5 € pour 3 articles à 12,50 €. Mais il affiche un total faux. Il y a un seul bug. Trouve-le.

JavaScript
let prix = 12.5;
let quantite = 3;
let total = prix + quantite;
console.log(`Total : ${total} €`);
Python
prix = 12.5
quantite = 3
total = prix + quantite
print(f"Total : {total} €")

Exercice

Un article coûte 20 € hors taxe, avec une TVA de 20 %. Écris un programme avec trois variables (prix_ht, tva, prix_ttc) qui calcule le prix toutes taxes comprises et affiche :

Résultat
Prix TTC : 24 €

Teste ensuite avec un prix hors taxe de 50 € : tu dois obtenir 60.

Corrigés

Question 1. À la fin, a vaut 1 et b vaut 8. b a reçu la valeur de a * 2 (donc 8) au moment où la ligne s'est exécutée ; changer a ensuite ne change pas b.

Question 2 : C. 2prix commence par un chiffre, prix total contient une espace, et prix-total contient un tiret, que le langage lirait comme une soustraction. Le tiret bas _ est autorisé.

Question 3. Les instructions s'exécutent l'une après l'autre, de haut en bas.

Question 4. JavaScript affiche 121 : "12" est du texte, donc le + colle les deux au lieu d'additionner. En Python, la même opération produit une TypeError. Dans les deux cas, la solution est de convertir d'abord : Number(age) + 1 ou int(age) + 1 donne 13.

Code à corriger. Le bug est dans l'opérateur : on a écrit prix + quantite (12.5 + 3 = 15.5) au lieu de prix * quantite. C'est un bug de logique : le programme fonctionne, mais il calcule autre chose que ce qu'on voulait. La bonne ligne est let total = prix * quantite; en JavaScript et total = prix * quantite en Python.

Exercice. Une solution :

JavaScript
let prixHt = 20;
let tva = 0.2;
let prixTtc = prixHt + prixHt * tva;
console.log(`Prix TTC : ${prixTtc} €`);
Python
prix_ht = 20
tva = 0.2
prix_ttc = prix_ht + prix_ht * tva
print(f"Prix TTC : {prix_ttc} €")

Remarque : Python affiche 24.0 (un nombre décimal garde sa décimale), JavaScript affiche 24. Les deux sont corrects. Avec un prix hors taxe de 50, tu obtiens bien 60.

4. Les conditions : faire des choix

Objectif : à la fin de ce chapitre, tu sais écrire un programme qui choisit quoi faire selon la situation, avec if, else, des comparaisons et des opérateurs logiques.

L'idée

Jusqu'ici, ton programme fait toujours la même chose, quoi qu'il arrive. Un vrai programme doit réagir : une remise si le panier est assez gros, un message d'erreur si le mot de passe est faux.

Pour cela, on pose une condition : une question dont la réponse est vrai ou faux (un booléen, tu te souviens ?). Si c'est vrai, on exécute un bloc d'instructions ; sinon, on en exécute un autre.

Comparer deux valeurs

Une comparaison produit un booléen :

  • égal à ? : === en JavaScript, == en Python ;
  • différent de ? : !== en JavaScript, != en Python ;
  • plus petit que ? : < dans les deux langages ;
  • plus petit ou égal ? : <= ;
  • plus grand que ? : > ;
  • plus grand ou égal ? : >=.

Attention : = range une valeur dans une variable (chapitre précédent), alors que == ou === compare. Les confondre est l'une des erreurs les plus fréquentes.

Un exemple pas à pas : la remise du magasin

Deuxième pièce du petit magasin : 10 % de remise dès 50 € d'achats, 20 % dès 100 €.

JavaScript
let total = 64;
let remise = 0;

if (total >= 100) {
  remise = 0.2;
} else if (total >= 50) {
  remise = 0.1;
} else {
  remise = 0;
}

let aPayer = total * (1 - remise);
console.log(`À payer : ${aPayer} €`);
Python
total = 64
remise = 0

if total >= 100:
    remise = 0.2
elif total >= 50:
    remise = 0.1
else:
    remise = 0

a_payer = total * (1 - remise)
print(f"À payer : {a_payer} €")

Résultat avec un total de 64 :

Résultat
À payer : 57.6 €

Comment ça se lit :

  • if (total >= 100) : si le total est d'au moins 100, on applique 20 % ;
  • else if (elif en Python) : sinon, et seulement si la première condition était fausse, on teste la suivante ;
  • else : si aucune condition n'était vraie, on exécute ce bloc.

Un seul des blocs s'exécute. Dès qu'une condition est vraie, l'ordinateur saute les suivantes.

Les accolades et l'indentation. En JavaScript, les blocs sont entourés d'accolades { }. En Python, il n'y en a pas : un bloc commence après les deux-points : et se reconnaît à son indentation (le décalage vers la droite, en général 4 espaces). En Python, l'indentation fait partie du code : si elle est fausse, le programme est faux.

L'ordre des conditions compte. Avec un total de 120, on veut 20 % de remise. On teste donc d'abord >= 100. Si on testait d'abord >= 50, 120 serait déjà « plus grand que 50 » : le premier bloc s'exécuterait, le deuxième serait ignoré, et on n'appliquerait que 10 %. On teste toujours le cas le plus précis (le plus grand) en premier.

Combiner des conditions

On peut combiner plusieurs conditions avec des mots logiques :

  • et (les deux conditions sont vraies) : && en JavaScript, and en Python ;
  • ou (au moins une est vraie) : || en JavaScript, or en Python ;
  • non (l'inverse) : ! en JavaScript, not en Python.

Par exemple, pour savoir si quelqu'un a entre 12 et 25 ans inclus :

JavaScript
if (age >= 12 && age <= 25) {
  console.log("Tarif jeune");
}
Python
if age >= 12 and age <= 25:
    print("Tarif jeune")

On peut aussi ranger le résultat d'une comparaison dans une variable booléenne : let estMajeur = age >= 18;.

À retenir

  • Une condition est une question dont la réponse est vrai ou faux ; if exécute un bloc seulement si c'est vrai.
  • else if / elif et else traitent les autres cas ; un seul bloc s'exécute.
  • Ne confonds pas = (ranger) et == / === (comparer).
  • On combine avec et, ou, non (&&, ||, ! en JavaScript ; and, or, not en Python).
  • Teste les cas du plus précis au plus général, et fais attention aux bornes (< ou <=).

Quiz

Question 1. Rappel du chapitre précédent : que vaut x après ces instructions ?

JavaScript
let x = 4;
x = x + 1;
Python
x = 4
x = x + 1

Question 2. Avec le programme de remise de ce chapitre et total = 50, quelle remise est appliquée : 0, 0.1 ou 0.2 ?

Question 3. Laquelle de ces conditions est vraie uniquement quand age est entre 12 et 25 inclus ?

  • A. age >= 12 || age <= 25 (JavaScript) / age >= 12 or age <= 25 (Python)
  • B. age >= 12 && age <= 25 (JavaScript) / age >= 12 and age <= 25 (Python)
  • C. age > 12 && age < 25 (JavaScript) / age > 12 and age < 25 (Python)

Question 4. On échange l'ordre des deux premiers tests : on vérifie d'abord total >= 50, puis total >= 100. Quelle remise obtient-on pour un total de 120 ? Pourquoi ?

Code à corriger

L'entrée est gratuite pour les moins de 12 ans. Mais à 12 ans pile, le programme dit encore « Gratuit ». Il y a un seul bug.

JavaScript
let age = 12;
if (age <= 12) {
  console.log("Gratuit");
} else {
  console.log("Payant");
}
Python
age = 12
if age <= 12:
    print("Gratuit")
else:
    print("Payant")

Exercice

Un cinéma propose trois tarifs :

  • moins de 12 ans : 5 € ;
  • de 12 à 25 ans (inclus) : 8 € ;
  • 26 ans et plus : 11 €.

Écris un programme qui, à partir d'une variable age, affiche Tarif : ... €. Teste-le avec tous ces âges et vérifie chaque résultat :

  • âge 8 : tarif attendu 5 € ;
  • âge 11 : 5 € ;
  • âge 12 : 8 € ;
  • âge 25 : 8 € ;
  • âge 26 : 11 € ;
  • âge 40 : 11 €.

Les âges 12, 25 et 26 sont les plus importants : ce sont les bornes, là où se cachent les bugs.

Corrigés

Question 1. x vaut 5. On calcule x + 1 avec la valeur actuelle de x (4), puis on range le résultat dans x.

Question 2. 0.1. Le premier test (total >= 100) est faux pour 50, le deuxième (total >= 50) est vrai : le signe >= inclut 50. Le total à payer est donc de 45 €.

Question 3 : B. Il faut que les deux conditions soient vraies, donc un « et ». Avec « ou » (A), presque tout le monde passe le test, puisque tout nombre est au moins 12 ou au plus 25. Avec > et < (C), on exclurait 12 et 25 eux-mêmes.

Question 4. On obtient 0.1, donc 10 % au lieu de 20 %. 120 est plus grand que 50 : le premier test est vrai, son bloc s'exécute, et le test >= 100 n'est jamais regardé. Il faut tester le cas le plus grand en premier.

Code à corriger. Le bug est sur la borne : age <= 12 accepte 12, alors que « moins de 12 ans » exclut 12. Il faut < à la place de <= :

JavaScript
if (age < 12) {
  console.log("Gratuit");
}
Python
if age < 12:
    print("Gratuit")

C'est un bug de logique classique : une comparaison correcte à un cheveu près. Dès que l'énoncé dit « moins de », « au moins », « jusqu'à », demande-toi si la valeur limite est incluse.

Exercice. Une solution :

JavaScript
let age = 25;

if (age < 12) {
  console.log("Tarif : 5 €");
} else if (age <= 25) {
  console.log("Tarif : 8 €");
} else {
  console.log("Tarif : 11 €");
}
Python
age = 25

if age < 12:
    print("Tarif : 5 €")
elif age <= 25:
    print("Tarif : 8 €")
else:
    print("Tarif : 11 €")

Remarque : on n'a pas besoin d'écrire age >= 12 and age <= 25 dans le deuxième test. Si on arrive dans le else if, c'est que age < 12 était faux : on sait déjà que age >= 12. Chaque test profite de ce que les précédents ont éliminé.

5. Les boucles : répéter sans se fatiguer

Objectif : à la fin de ce chapitre, tu sais répéter des instructions avec while et for, accumuler un résultat au fil des tours, et éviter qu'une boucle ne tourne pour toujours.

L'idée

Imagine que tu doives afficher les nombres de 1 à 100. Écrire cent fois console.log serait long, ennuyeux, et plein de risques d'erreur. Une boucle demande à l'ordinateur de répéter un bloc d'instructions : il adore ça, il ne se fatigue jamais.

Il existe deux grandes boucles :

  • while (« tant que ») : on répète tant qu'une condition est vraie. Pratique quand on ne sait pas à l'avance combien de tours il faudra ;
  • for (« pour ») : on répète un nombre de fois connu, ou pour chaque élément d'un ensemble.

La boucle while

JavaScript
let i = 1;
while (i <= 3) {
  console.log(i);
  i = i + 1;
}
Python
i = 1
while i <= 3:
    print(i)
    i = i + 1

Résultat :

Résultat
1
2
3

Suivons-la comme le ferait l'ordinateur :

  • au départ, i vaut 1 ;
  • on teste i <= 3. C'est vrai : on affiche 1, puis i passe à 2 ;
  • on reteste : vrai, on affiche 2, i passe à 3 ;
  • on reteste : vrai, on affiche 3, i passe à 4 ;
  • on reteste : 4 <= 3 est faux : la boucle s'arrête, et le programme continue après le bloc.

Le test se fait avant chaque tour, y compris le premier.

La boucle for

Quand on connaît le nombre de tours, for est plus compact : il gère lui-même le compteur.

JavaScript
for (let i = 1; i <= 3; i++) {
  console.log(i);
}
Python
for i in range(1, 4):
    print(i)

Ces deux programmes affichent exactement la même chose que le while ci-dessus.

  • En JavaScript, les trois parties entre parenthèses sont : le départ (let i = 1), la condition pour continuer (i <= 3) et la mise à jour à la fin de chaque tour (i++, qui veut dire « ajoute 1 à i »).
  • En Python, range(1, 4) produit les nombres de 1 inclus à 4 exclu : 1, 2, 3. La borne de fin n'est jamais atteinte. range(5) produit 0, 1, 2, 3, 4 : cinq nombres.

Un exemple pas à pas : le prix de plusieurs articles

Pour ton petit magasin : un article coûte 4 €. Affichons ce que coûtent de 1 à 5 articles.

JavaScript
let prix = 4;
for (let quantite = 1; quantite <= 5; quantite++) {
  console.log(`${quantite} article(s) : ${prix * quantite} €`);
}
Python
prix = 4
for quantite in range(1, 6):
    print(f"{quantite} article(s) : {prix * quantite} €")

Résultat :

Résultat
1 article(s) : 4 €
2 article(s) : 8 €
3 article(s) : 12 €
4 article(s) : 16 €
5 article(s) : 20 €

L'accumulateur : construire un résultat tour après tour

Une boucle sert très souvent à accumuler : on prépare une variable avant la boucle, et on la fait évoluer à chaque tour. Ici, la somme des nombres de 1 à 100 :

JavaScript
let somme = 0;
for (let i = 1; i <= 100; i++) {
  somme = somme + i;
}
console.log(somme);
Python
somme = 0
for i in range(1, 101):
    somme = somme + i
print(somme)

Résultat : 5050. La variable somme démarre à 0, et chaque tour y ajoute le nombre en cours. C'est exactement ce qu'on fera pour totaliser un panier.

Sortir d'une boucle avec break

break arrête la boucle immédiatement. Par exemple, pour trouver le premier multiple de 7 supérieur à 50 :

JavaScript
let n = 51;
while (true) {
  if (n % 7 === 0) {
    break;
  }
  n = n + 1;
}
console.log(n);
Python
n = 51
while True:
    if n % 7 == 0:
        break
    n = n + 1
print(n)

Résultat : 56. La condition true est toujours vraie : seule l'instruction break arrête cette boucle.

Le danger : la boucle infinie

Si la condition d'un while ne devient jamais fausse, la boucle ne s'arrête jamais. C'est une boucle infinie : le programme semble figé. Cela arrive presque toujours parce qu'on a oublié de faire évoluer la variable testée.

Si ton programme tourne sans fin dans un terminal, arrête-le avec Ctrl + C. Dans la console d'un navigateur, il faudra fermer l'onglet. Pense à toujours te demander : « qu'est-ce qui fera arrêter cette boucle ? »

À retenir

  • Une boucle répète un bloc d'instructions ; while répète tant qu'une condition est vraie, for répète un nombre de fois connu.
  • Le test d'un while se fait avant chaque tour.
  • En Python, range(a, b) va de a inclus à b exclu.
  • Un accumulateur (somme = somme + ...) construit un résultat tour après tour.
  • Une boucle doit toujours avoir une façon de s'arrêter : sinon, c'est une boucle infinie.

Quiz

Question 1. Qu'affiche ce programme ?

JavaScript
for (let i = 1; i < 4; i++) {
  console.log(i * 2);
}
Python
for i in range(1, 4):
    print(i * 2)

Question 2. Combien de fois le mot « Salut » est-il affiché ?

JavaScript
for (let i = 1; i < 5; i++) {
  console.log("Salut");
}
Python
for i in range(1, 5):
    print("Salut")

Question 3. Rappel du chapitre précédent : qu'affiche ce programme ? Pense à ce que fait le % (le reste de la division).

JavaScript
for (let i = 1; i <= 6; i++) {
  if (i % 2 === 0) {
    console.log(i);
  }
}
Python
for i in range(1, 7):
    if i % 2 == 0:
        print(i)

Question 4. Pourquoi ne faut-il pas écrire while (true) sans prévoir de break ?

Code à corriger

Ce programme devait afficher 1, 2, 3 puis s'arrêter. À la place, il affiche 1 sans fin. Il y a un seul bug.

Attention : ne le lance pas dans la console d'un navigateur, il la gèlerait. Si tu le lances ailleurs, arrête-le avec Ctrl + C.

JavaScript
let i = 1;
while (i <= 3) {
  console.log(i);
}
Python
i = 1
while i <= 3:
    print(i)

Exercice

Tu épargnes 25 € par mois. Combien de mois te faut-il pour atteindre 300 € ? Écris un programme avec une boucle while qui ajoute 25 € à ton épargne à chaque mois qui passe, compte les mois, et affiche à la fin :

Résultat
Objectif atteint en 12 mois

Vérifie avec un autre objectif : avec 130 € à atteindre, tu dois obtenir 6 mois (25 × 6 = 150, et 25 × 5 = 125 n'est pas encore assez). C'est ce deuxième test qui prouve que ta condition est correcte.

Corrigés

Question 1. Le programme affiche 2, 4 puis 6. Les valeurs de i sont 1, 2, 3 (la valeur 4 est exclue), et on affiche chaque fois i * 2.

Question 2. 4 fois : i prend les valeurs 1, 2, 3 et 4. La borne de fin (5) est exclue, dans i < 5 comme dans range(1, 5). C'est une erreur très fréquente : pour répéter 5 fois, il faut range(5) ou i de 0 à 4, ou de 1 à 5 avec <= 5.

Question 3. Le programme affiche 2, 4 puis 6 : la boucle passe en revue 1 à 6, et la condition i % 2 === 0 ne laisse passer que les nombres dont le reste de la division par 2 est zéro, c'est-à-dire les nombres pairs.

Question 4. Parce que true est toujours vrai : sans break, rien n'arrêterait jamais la boucle, qui deviendrait infinie.

Code à corriger. Le programme oublie de faire évoluer i : il vaut toujours 1, donc i <= 3 est toujours vrai et la boucle ne s'arrête jamais. Il manque l'instruction qui fait avancer le compteur :

JavaScript
let i = 1;
while (i <= 3) {
  console.log(i);
  i = i + 1;
}
Python
i = 1
while i <= 3:
    print(i)
    i = i + 1

C'est la cause numéro un des boucles infinies : la variable du test n'est jamais modifiée dans le bloc.

Exercice. Une solution :

JavaScript
let objectif = 300;
let epargne = 0;
let mois = 0;

while (epargne < objectif) {
  epargne = epargne + 25;
  mois = mois + 1;
}

console.log(`Objectif atteint en ${mois} mois`);
Python
objectif = 300
epargne = 0
mois = 0

while epargne < objectif:
    epargne = epargne + 25
    mois = mois + 1

print(f"Objectif atteint en {mois} mois")

Avec objectif = 130, ce programme affiche Objectif atteint en 6 mois. Remarque que la condition est epargne < objectif (strictement plus petit) : on s'arrête dès que l'épargne atteint ou dépasse l'objectif. Avec objectif = 300, l'épargne vaut exactement 300 au 12e mois, la condition devient fausse, et on s'arrête : c'est bien le bon nombre de mois.

6. Les fonctions : des recettes qu'on réutilise

Objectif : à la fin de ce chapitre, tu sais écrire et appeler une fonction avec des paramètres et une valeur de retour, et tu sais pourquoi return n'est pas la même chose qu'afficher.

L'idée

Dans le magasin, tu as écrit le calcul de la remise. Si tu en as besoin pour trois clients, tu vas copier ce bloc trois fois ? Et si la règle change (la remise passe à 15 %), tu devras la corriger trois fois, sans en oublier une.

Une fonction est une recette à laquelle on donne un nom. On l'écrit une fois ; on l'appelle autant de fois qu'on veut. Elle a quatre ingrédients :

  • un nom (prixApresRemise) ;
  • des paramètres : les « ingrédients » qu'on lui donne (total) ;
  • un corps : les instructions qu'elle exécute ;
  • un résultat renvoyé avec le mot return.

Écrire une fonction, c'est la définir : cela ne l'exécute pas. Elle ne s'exécute que lorsqu'on l'appelle.

Un exemple pas à pas : la remise dans une fonction

Reprenons les règles du chapitre 4 : 10 % dès 50 €, 20 % dès 100 €.

JavaScript
function prixApresRemise(total) {
  let remise = 0;
  if (total >= 100) {
    remise = 0.2;
  } else if (total >= 50) {
    remise = 0.1;
  }
  return total * (1 - remise);
}

console.log(prixApresRemise(64));
console.log(prixApresRemise(120));
console.log(prixApresRemise(30));
Python
def prix_apres_remise(total):
    remise = 0
    if total >= 100:
        remise = 0.2
    elif total >= 50:
        remise = 0.1
    return total * (1 - remise)


print(prix_apres_remise(64))
print(prix_apres_remise(120))
print(prix_apres_remise(30))

Résultat (en Python, 96 s'affiche 96.0, car c'est un nombre décimal) :

Résultat
57.6
96
30

Décortiquons :

  • en JavaScript, on définit avec le mot function ; en Python, avec def et un deux-points ;
  • total est le paramètre : un nom, à l'intérieur de la fonction, pour la valeur qu'on lui donnera ;
  • prixApresRemise(64) est un appel : 64 est l'argument, la vraie valeur qui prend la place de total pour ce tour-là ;
  • return renvoie le résultat à l'endroit de l'appel et arrête la fonction. On peut ranger ce résultat dans une variable, l'afficher, ou s'en servir dans un autre calcul.

Une fonction avec plusieurs paramètres les reçoit dans l'ordre : function prixTotal(prix, quantite) s'appelle avec prixTotal(12.5, 3).

return n'est pas print

C'est la confusion la plus fréquente des débutants. print (ou console.log) affiche un texte à l'écran pour un humain. return renvoie une valeur au reste du programme.

Qu'arrive-t-il si une fonction affiche, mais ne renvoie rien ?

JavaScript
function saluer(nom) {
  console.log("Bonjour " + nom);
}

console.log(saluer("Ada"));
Python
def saluer(nom):
    print("Bonjour " + nom)


print(saluer("Ada"))

Le programme affiche d'abord Bonjour Ada (dans la fonction), puis undefined en JavaScript, None en Python. Une fonction qui n'a pas de return renvoie « rien » : undefined ou None, qui veulent dire « il n'y a pas de valeur ». Si tu essaies de calculer avec ce « rien », tu auras un problème.

Les variables d'une fonction restent chez elle

Les variables créées dans une fonction, comme remise plus haut, n'existent que dans cette fonction. C'est la portée (scope). En dehors, elles sont inconnues :

JavaScript
console.log(remise);
Python
print(remise)

Ces lignes, placées après l'appel de la fonction, produisent ReferenceError: remise is not defined en JavaScript et NameError: name 'remise' is not defined en Python. Si une fonction doit communiquer un résultat, elle le fait par son return, pas en laissant traîner ses variables.

À retenir

  • Une fonction est une recette nommée : on la définit une fois, on l'appelle plusieurs fois.
  • Les paramètres sont les noms des valeurs reçues ; les arguments sont les valeurs données à l'appel, dans l'ordre.
  • return renvoie un résultat et arrête la fonction ; sans return, on obtient undefined (JavaScript) ou None (Python).
  • return ≠ afficher : afficher est pour l'humain, return est pour le programme.
  • Les variables d'une fonction sont locales : invisibles à l'extérieur.

Quiz

Question 1. Que vaut double(4) ?

JavaScript
function double(n) {
  return n * 2;
}
Python
def double(n):
    return n * 2

Question 2. Rappel du chapitre précédent : combien de nombres ce programme affiche-t-il, et lesquels ?

JavaScript
for (let i = 1; i <= 3; i++) {
  console.log(double(i));
}
Python
for i in range(1, 4):
    print(double(i))

Question 3. Quelle est la différence entre console.log(x) / print(x) et return x dans une fonction ?

Question 4. Qu'affiche la dernière ligne de ce programme, et pourquoi ?

JavaScript
function saluer(nom) {
  console.log("Bonjour " + nom);
}
console.log(saluer("Ada"));
Python
def saluer(nom):
    print("Bonjour " + nom)

print(saluer("Ada"))

Code à corriger

Cette fonction doit calculer un prix toutes taxes comprises (TVA de 20 %), puis le programme ajoute 5 € de frais de port. Mais le résultat est faux. Il y a un seul bug.

JavaScript
function ttc(ht) {
  console.log(ht * 1.2);
}

let prix = ttc(50);
console.log("Avec le port : " + (prix + 5));
Python
def ttc(ht):
    print(ht * 1.2)


prix = ttc(50)
print("Avec le port : " + str(prix + 5))

Le résultat attendu est Avec le port : 65.

Exercice

Écris deux fonctions :

  1. tarifCinema(age) (ou tarif_cinema(age) en Python) qui renvoie le tarif de séance du chapitre 4 : moins de 12 ans, 5 € ; de 12 à 25 ans, 8 € ; au-delà, 11 € ;
  2. sommeJusqua(n) (ou somme_jusqua(n)) qui renvoie la somme des nombres de 1 à n (pour n = 4, c'est 1 + 2 + 3 + 4 = 10).

Teste-les avec des appels affichés : tarifCinema(12) doit donner 8, tarifCinema(26) doit donner 11, sommeJusqua(4) doit donner 10, et sommeJusqua(100) doit donner 5050 (tu connais déjà ce résultat).

Utilise bien return dans les deux fonctions : c'est le but de l'exercice.

Corrigés

Question 1. double(4) vaut 8. L'argument 4 prend la place du paramètre n, la fonction calcule 4 * 2, et return renvoie ce résultat.

Question 2. Trois nombres : 2, 4 et 6. Pour i valant 1, 2 puis 3 (en Python, range(1, 4) s'arrête avant 4), on appelle double(i) et on affiche ce qu'elle renvoie.

Question 3. console.log / print affiche une valeur à l'écran, pour un humain, et ne la rend pas disponible au reste du programme. return renvoie la valeur à l'endroit de l'appel, où l'on peut la ranger dans une variable ou la réutiliser dans un calcul.

Question 4. La dernière ligne affiche Bonjour Ada (par la fonction), puis undefined en JavaScript ou None en Python. La fonction n'a pas de return : elle ne renvoie « rien », et c'est ce « rien » que l'on affiche ensuite.

Code à corriger. Le bug est que ttc affiche son résultat au lieu de le renvoyer : prix reçoit donc undefined (JavaScript) ou None (Python). En JavaScript, undefined + 5 donne NaN (« not a number »), en Python l'addition provoque une TypeError. Il faut remplacer l'affichage par un return :

JavaScript
function ttc(ht) {
  return ht * 1.2;
}

let prix = ttc(50);
console.log("Avec le port : " + (prix + 5));
Python
def ttc(ht):
    return ht * 1.2


prix = ttc(50)
print("Avec le port : " + str(prix + 5))

Le programme affiche maintenant Avec le port : 65 (65.0 en Python). Quand une fonction calcule quelque chose dont on se servira ensuite, elle doit le renvoyer.

Exercice. Une solution :

JavaScript
function tarifCinema(age) {
  if (age < 12) {
    return 5;
  } else if (age <= 25) {
    return 8;
  }
  return 11;
}

function sommeJusqua(n) {
  let somme = 0;
  for (let i = 1; i <= n; i++) {
    somme = somme + i;
  }
  return somme;
}

console.log(tarifCinema(12));
console.log(tarifCinema(26));
console.log(sommeJusqua(4));
console.log(sommeJusqua(100));
Python
def tarif_cinema(age):
    if age < 12:
        return 5
    elif age <= 25:
        return 8
    return 11


def somme_jusqua(n):
    somme = 0
    for i in range(1, n + 1):
        somme = somme + i
    return somme


print(tarif_cinema(12))
print(tarif_cinema(26))
print(somme_jusqua(4))
print(somme_jusqua(100))

Résultat : 8, 11, 10 et 5050. Observe deux choses : les return à l'intérieur des if arrêtent la fonction immédiatement (on n'a donc pas besoin d'un else final), et range(1, n + 1) inclut bien n, car la borne de fin de range est exclue.

7. Les listes : plusieurs valeurs d'un coup

Objectif : à la fin de ce chapitre, tu sais ranger plusieurs valeurs dans une liste, lire un élément grâce à son indice, ajouter des éléments, et parcourir toute la liste avec une boucle.

L'idée

Un client achète trois articles. Va-t-on créer prix1, prix2, prix3 ? Et pour cinquante articles ? Une liste (on dit aussi un tableau, array en JavaScript) range plusieurs valeurs dans une seule variable, dans l'ordre.

JavaScript
let panier = [12.5, 3, 7.9];
Python
panier = [12.5, 3, 7.9]

Une liste s'écrit entre crochets, avec des virgules entre les éléments. Elle peut contenir n'importe quel type de valeurs : des nombres, des textes, et même d'autres listes.

Les indices commencent à zéro

Chaque élément a une position, appelée indice. Le point surprenant : on compte à partir de 0. Le premier élément est à l'indice 0, le deuxième à l'indice 1, et ainsi de suite.

JavaScript
let courses = ["pain", "lait", "œufs"];
console.log(courses[0]);
console.log(courses[1]);
console.log(courses.length);
Python
courses = ["pain", "lait", "œufs"]
print(courses[0])
print(courses[1])
print(len(courses))

Résultat :

Résultat
pain
lait
3

courses[0] est « pain » (le premier), courses[1] est « lait » (le deuxième). La taille de la liste s'obtient avec .length en JavaScript et len(...) en Python : ici 3. Comme on compte depuis 0, le dernier indice vaut toujours taille - 1 : ici 2.

On peut aussi modifier un élément (courses[1] = "jus"), ajouter un élément à la fin (push en JavaScript, append en Python), et même en retirer :

JavaScript
courses.push("beurre");
console.log(courses.length);
Python
courses.append("beurre")
print(len(courses))

La liste contient maintenant 4 éléments.

Parcourir une liste avec une boucle

Le grand avantage des listes, c'est qu'elles se marient avec les boucles : on traite chaque élément à tour de rôle.

JavaScript
let panier = [12.5, 3, 7.9];
let total = 0;

for (const prix of panier) {
  total = total + prix;
}

console.log(`Total : ${total} €`);
Python
panier = [12.5, 3, 7.9]
total = 0

for prix in panier:
    total = total + prix

print(f"Total : {total} €")

Résultat :

Résultat
Total : 23.4 €

Lis la boucle à voix haute : « pour chaque prix dans panier, ajoute-le au total ». À chaque tour, la variable prix prend la valeur de l'élément suivant : 12.5, puis 3, puis 7.9. C'est l'accumulateur du chapitre précédent, appliqué à un vrai panier.

On peut aussi ajouter une condition dans la boucle pour filtrer : par exemple compter les articles qui coûtent plus de 5 €.

JavaScript
let chers = 0;
for (const prix of panier) {
  if (prix > 5) {
    chers = chers + 1;
  }
}
console.log(chers);
Python
chers = 0
for prix in panier:
    if prix > 5:
        chers = chers + 1
print(chers)

Le résultat est 2 (le 12.5 et le 7.9).

L'erreur classique : sortir de la liste

Que se passe-t-il si on demande un indice qui n'existe pas ? Pour la liste de 3 éléments, panier[3] n'existe pas (les indices valides sont 0, 1 et 2).

  • Python s'arrête avec une erreur claire : IndexError: list index out of range.
  • JavaScript ne dit rien : il renvoie undefined. L'erreur se cache, et réapparaît plus loin sous forme de NaN dans un calcul. C'est plus sournois.

C'est ce qu'on appelle une erreur de décalage d'un cran (off-by-one) : on va un élément trop loin, ou un de moins.

À retenir

  • Une liste range plusieurs valeurs dans l'ordre : [12.5, 3, 7.9].
  • Les indices commencent à 0 ; le dernier indice vaut taille - 1.
  • La taille s'obtient avec .length (JavaScript) ou len(...) (Python).
  • On ajoute à la fin avec push (JavaScript) ou append (Python).
  • for (const x of liste) / for x in liste: parcourt chaque élément.
  • Sortir de la liste est une erreur : IndexError en Python, undefined silencieux en JavaScript.

Quiz

Question 1. Avec courses = ["pain", "lait", "œufs"], que vaut courses[1] ?

Question 2. Une liste contient 5 éléments. Quel est l'indice du dernier ?

Question 3. Rappel du chapitre précédent : combien de fois cette boucle s'exécute-t-elle ?

JavaScript
let notes = [12, 15, 9, 18];
for (let i = 0; i < notes.length; i++) {
  console.log(notes[i]);
}
Python
notes = [12, 15, 9, 18]
for i in range(len(notes)):
    print(notes[i])

Question 4. Rappel du chapitre sur les fonctions : que renvoie cette fonction pour [2, 5, 3] ?

JavaScript
function plusGrand(liste) {
  let max = liste[0];
  for (const x of liste) {
    if (x > max) {
      max = x;
    }
  }
  return max;
}
Python
def plus_grand(liste):
    maximum = liste[0]
    for x in liste:
        if x > maximum:
            maximum = x
    return maximum

Code à corriger

Ce programme doit totaliser le panier ([12.5, 3, 7.9, 4], soit 27.4). Mais il plante en Python, et affiche NaN en JavaScript. Il y a un seul bug.

JavaScript
let panier = [12.5, 3, 7.9, 4];
let total = 0;
for (let i = 0; i <= panier.length; i++) {
  total = total + panier[i];
}
console.log(total);
Python
panier = [12.5, 3, 7.9, 4]
total = 0
for i in range(len(panier) + 1):
    total = total + panier[i]
print(total)

Exercice

Un professeur veut calculer la moyenne d'une classe. Écris une fonction moyenne(notes) qui renvoie la moyenne d'une liste de notes (la somme des notes divisée par leur nombre).

  • pour [12, 15, 9, 18], elle doit renvoyer 13.5 ;
  • écris ensuite une deuxième fonction nombreDeReussites(notes) (nombre_de_reussites en Python) qui renvoie combien de notes valent 12 ou plus : pour la même liste, 3.

Pour aller plus loin : que se passe-t-il si la liste est vide ([]) ? Teste-le, puis fais en sorte que ta fonction moyenne renvoie 0 dans ce cas, avec une condition du chapitre 4.

Corrigés

Question 1. "lait". Les indices commencent à 0 : courses[0] est "pain", courses[1] est "lait".

Question 2. L'indice 4. Pour une liste de taille n, les indices vont de 0 à n - 1.

Question 3. Quatre fois : la liste a 4 éléments, i prend les valeurs 0, 1, 2 et 3 (la condition i < notes.length exclut 4, et range(len(notes)) s'arrête avant 4). Le programme affiche 12, 15, 9, 18.

Question 4. La fonction renvoie 5 : elle garde en mémoire le plus grand élément vu jusqu'ici, qu'elle met à jour quand elle en trouve un plus grand.

Code à corriger. La boucle va un cran trop loin. La liste a 4 éléments (indices 0 à 3), mais la boucle va jusqu'à l'indice 4 : i <= panier.length accepte 4, et range(len(panier) + 1) aussi. L'élément panier[4] n'existe pas : undefined en JavaScript (d'où NaN), IndexError en Python. Il faut s'arrêter avant la taille :

JavaScript
for (let i = 0; i < panier.length; i++) {
  total = total + panier[i];
}
Python
for i in range(len(panier)):
    total = total + panier[i]

Le programme affiche alors 27.4. Encore plus simple : parcourir directement les éléments avec for (const prix of panier) ou for prix in panier, comme dans le chapitre, rend ce bug impossible.

Exercice. Une solution :

JavaScript
function moyenne(notes) {
  if (notes.length === 0) {
    return 0;
  }
  let somme = 0;
  for (const note of notes) {
    somme = somme + note;
  }
  return somme / notes.length;
}

function nombreDeReussites(notes) {
  let compteur = 0;
  for (const note of notes) {
    if (note >= 12) {
      compteur = compteur + 1;
    }
  }
  return compteur;
}

console.log(moyenne([12, 15, 9, 18]));
console.log(nombreDeReussites([12, 15, 9, 18]));
console.log(moyenne([]));
Python
def moyenne(notes):
    if len(notes) == 0:
        return 0
    somme = 0
    for note in notes:
        somme = somme + note
    return somme / len(notes)


def nombre_de_reussites(notes):
    compteur = 0
    for note in notes:
        if note >= 12:
            compteur = compteur + 1
    return compteur


print(moyenne([12, 15, 9, 18]))
print(nombre_de_reussites([12, 15, 9, 18]))
print(moyenne([]))

Résultat : 13.5, 3 et 0. Sans la condition sur la liste vide, la division par zéro donne NaN en JavaScript et une ZeroDivisionError en Python : traiter les cas limites, comme une liste vide, fait partie du métier.

8. Les dictionnaires : retrouver par un nom

Objectif : à la fin de ce chapitre, tu sais associer des valeurs à des clés dans un dictionnaire, lire, ajouter et modifier une valeur, parcourir ses éléments, et combiner listes et dictionnaires pour représenter un panier.

L'idée

Dans une liste, on retrouve un élément par sa position : « le troisième ». Mais pour un catalogue de prix, ce n'est pas pratique : tu veux demander « combien coûte le pain ? », pas « combien coûte l'élément numéro 1 ? ».

Un dictionnaire (on dit un objet en JavaScript) associe des clés à des valeurs. Comme dans un vrai dictionnaire, on cherche par le mot, pas par le numéro de page.

JavaScript
let catalogue = { pomme: 0.5, pain: 1.2, lait: 1.1 };
Python
catalogue = {"pomme": 0.5, "pain": 1.2, "lait": 1.1}

Un dictionnaire s'écrit entre accolades. Chaque entrée est une paire clé : valeur, séparées par des virgules. Ici, les clés sont les noms des articles, les valeurs sont leurs prix.

Lire, modifier, ajouter

On lit la valeur d'une clé en écrivant la clé entre crochets, comme pour une liste, mais avec un nom au lieu d'un indice :

JavaScript
console.log(catalogue["pain"]);
catalogue["pain"] = catalogue["pain"] + 0.1;
console.log(catalogue["pain"]);
catalogue["fraise"] = 3;
Python
print(catalogue["pain"])
catalogue["pain"] = catalogue["pain"] + 0.1
print(catalogue["pain"])
catalogue["fraise"] = 3

Le programme affiche 1.2, puis 1.3 : on a augmenté le prix du pain de 0,10 €. La dernière ligne ajoute une entrée : si la clé n'existe pas encore, l'affectation la crée. En JavaScript, on peut aussi écrire catalogue.pain à la place de catalogue["pain"].

Les clés sont sensibles à la casse : "pain" et "Pain" sont deux clés différentes.

Que se passe-t-il si la clé n'existe pas ?

Demande le prix d'un article qui n'est pas au catalogue :

JavaScript
console.log(catalogue["kiwi"]);
Python
print(catalogue["kiwi"])
  • JavaScript renvoie undefined, sans broncher ;
  • Python s'arrête avec KeyError: 'kiwi'.

Pour vérifier avant de lire, on utilise in, qui répond par un booléen : "kiwi" in catalogue vaut false (JavaScript) ou False (Python), tandis que "pain" in catalogue est vrai. Combiné avec un if, on évite l'erreur.

Parcourir un dictionnaire

JavaScript
for (const [nom, prix] of Object.entries(catalogue)) {
  console.log(`${nom} : ${prix} €`);
}
Python
for nom, prix in catalogue.items():
    print(f"{nom} : {prix} €")

À chaque tour, nom reçoit une clé et prix sa valeur. Les dictionnaires gardent l'ordre dans lequel on a ajouté les entrées.

Un exemple pas à pas : le panier du magasin

Tu peux maintenant représenter un vrai panier : une liste de dictionnaires, un par ligne d'achat. Le catalogue donne les prix ; le panier dit quoi et combien.

JavaScript
let catalogue = { pomme: 0.5, pain: 1.2, lait: 1.1 };

let panier = [
  { nom: "pomme", quantite: 4 },
  { nom: "pain", quantite: 2 },
  { nom: "lait", quantite: 1 },
];

let total = 0;
for (const ligne of panier) {
  let prix = catalogue[ligne.nom];
  total = total + prix * ligne.quantite;
}

console.log(`Total : ${total} €`);
Python
catalogue = {"pomme": 0.5, "pain": 1.2, "lait": 1.1}

panier = [
    {"nom": "pomme", "quantite": 4},
    {"nom": "pain", "quantite": 2},
    {"nom": "lait", "quantite": 1},
]

total = 0
for ligne in panier:
    prix = catalogue[ligne["nom"]]
    total = total + prix * ligne["quantite"]

print(f"Total : {total} €")

Résultat :

Résultat
Total : 5.5 €

Suis le programme : pour la première ligne du panier, ligne["nom"] vaut "pomme", on cherche son prix dans le catalogue (0.5), on le multiplie par la quantité (4), et on ajoute 2 au total. Puis 2.4 pour le pain, 1.1 pour le lait : 5.5 €. Tu viens de combiner trois chapitres : une boucle, des listes, des dictionnaires.

À retenir

  • Un dictionnaire associe des clés à des valeurs : { pomme: 0.5 } / {"pomme": 0.5}.
  • On lit et on modifie avec catalogue["pain"] ; affecter à une clé qui n'existe pas l'ajoute.
  • Une clé absente donne undefined (JavaScript) ou une KeyError (Python) : vérifie avec in.
  • Les clés sont sensibles à la casse.
  • On parcourt avec Object.entries(...) (JavaScript) ou .items() (Python).
  • Liste = par position, dictionnaire = par nom ; on les combine volontiers.

Quiz

Question 1. Avec le catalogue de ce chapitre, que vaut catalogue["lait"] ?

Question 2. Que se passe-t-il avec catalogue["Pomme"] (avec un P majuscule) en Python ? Et en JavaScript ?

Question 3. Rappel du chapitre précédent : dans quel cas préfères-tu une liste, et dans quel cas préfères-tu un dictionnaire ?

Question 4. Après ces instructions, que vaut catalogue["pain"] ?

JavaScript
let catalogue = { pain: 1.2 };
catalogue["pain"] = catalogue["pain"] + 0.1;
Python
catalogue = {"pain": 1.2}
catalogue["pain"] = catalogue["pain"] + 0.1

Code à corriger

Ce programme doit afficher le prix du pain, mais le client demande « Pain » avec une majuscule. En Python il plante ; en JavaScript il affiche Prix : undefined €. Corrige le programme pour qu'il affiche un message poli (Article inconnu) quand l'article n'est pas au catalogue, au lieu de planter ou d'afficher n'importe quoi.

JavaScript
let catalogue = { pomme: 0.5, pain: 1.2 };
let article = "Pain";
console.log(`Prix : ${catalogue[article]} €`);
Python
catalogue = {"pomme": 0.5, "pain": 1.2}
article = "Pain"
print(f"Prix : {catalogue[article]} €")

Exercice

Écris un programme qui compte les mots d'une phrase. Avec la phrase "le chat et le chien et le chat", il doit produire un dictionnaire qui dit combien de fois chaque mot apparaît :

Résultat
le : 3
chat : 2
et : 2
chien : 1

Indice : la phrase se découpe en mots avec phrase.split(" ") (les deux langages ont cette méthode, et elle renvoie une liste de mots). Pour chaque mot, soit il est déjà dans le dictionnaire (tu ajoutes 1 à son compteur), soit il n'y est pas encore (tu le crées avec la valeur 1).

Corrigés

Question 1. 1.1.

Question 2. Les clés sont sensibles à la casse : "Pomme" n'existe pas dans le catalogue (seule "pomme" existe). Python s'arrête avec KeyError: 'Pomme'. JavaScript, lui, renvoie undefined sans prévenir, ce qui donne Prix : undefined € si on affiche la valeur.

Question 3. On préfère une liste quand on a une suite de valeurs dans l'ordre qu'on parcourt ou qu'on retrouve par position (des prix, des notes). On préfère un dictionnaire quand on veut retrouver une valeur par un nom (le prix du pain, l'âge de Ada).

Question 4. 1.3. On lit la valeur actuelle (1.2), on lui ajoute 0.1, et on range le résultat dans la même clé.

Code à corriger. Le programme lit la clé sans vérifier qu'elle existe. Il faut tester avec in avant de lire :

JavaScript
let catalogue = { pomme: 0.5, pain: 1.2 };
let article = "Pain";

if (article in catalogue) {
  console.log(`Prix : ${catalogue[article]} €`);
} else {
  console.log("Article inconnu");
}
Python
catalogue = {"pomme": 0.5, "pain": 1.2}
article = "Pain"

if article in catalogue:
    print(f"Prix : {catalogue[article]} €")
else:
    print("Article inconnu")

Le programme affiche Article inconnu : on vérifie qu'une clé existe avant de la lire, plutôt que d'espérer. (Tu pourrais aussi convertir le nom en minuscules avant la recherche, avec article.toLowerCase() en JavaScript ou article.lower() en Python, pour que « Pain » trouve « pain ».)

Exercice. Une solution :

JavaScript
let phrase = "le chat et le chien et le chat";
let compteur = {};

for (const mot of phrase.split(" ")) {
  if (mot in compteur) {
    compteur[mot] = compteur[mot] + 1;
  } else {
    compteur[mot] = 1;
  }
}

for (const [mot, nombre] of Object.entries(compteur)) {
  console.log(`${mot} : ${nombre}`);
}
Python
phrase = "le chat et le chien et le chat"
compteur = {}

for mot in phrase.split(" "):
    if mot in compteur:
        compteur[mot] = compteur[mot] + 1
    else:
        compteur[mot] = 1

for mot, nombre in compteur.items():
    print(f"{mot} : {nombre}")

Le résultat est le : 3, chat : 2, et : 2, chien : 1. Ce schéma (« s'il est déjà là, ajoute 1 ; sinon, crée-le à 1 ») est l'un des plus utilisés en programmation : tu le retrouveras pour compter n'importe quoi.

9. Déboguer : trouver et corriger un bug

Objectif : à la fin de ce chapitre, tu sais reconnaître les trois sortes d'erreurs, lire un message d'erreur, et corriger un bug avec une méthode au lieu de tâtonner.

L'idée

Tous les programmeurs, débutants comme expérimentés, passent une bonne partie de leur temps à chercher des bugs. Ce n'est pas un signe que tu es mauvais : c'est le métier. La différence entre un débutant frustré et un développeur efficace n'est pas qu'il fait moins d'erreurs, c'est qu'il a une méthode pour les trouver.

Tu en as déjà rencontré tout au long du cours. Ce chapitre les range en trois familles et te donne une méthode.

Les trois sortes d'erreurs

1. L'erreur de syntaxe. Le code est mal écrit : un guillemet manquant, une parenthèse oubliée, une indentation fausse. Le programme refuse de démarrer et te dit où (chapitre 2). C'est la plus facile à corriger : le message pointe presque toujours la ligne.

2. L'erreur d'exécution. Le code est bien écrit, le programme démarre, puis il plante en route parce qu'il fait quelque chose d'impossible : lire l'indice d'une liste qui n'existe pas (IndexError), diviser par zéro (ZeroDivisionError), lire une clé absente (KeyError), utiliser une variable qui n'existe pas (NameError / ReferenceError).

3. L'erreur de logique. Le programme tourne jusqu'au bout sans aucun message, mais le résultat est faux : + au lieu de * (chapitre 3), <= au lieu de < (chapitre 4). C'est la plus sournoise, car personne ne te dit qu'il y a un problème. Seule ta tête sait ce que le programme devrait afficher.

Lire un message d'erreur

Quand le programme plante, lis le message en entier, par la fin. Voici un programme Python qui divise par zéro :

Python
def diviser(a, b):
    return a / b


print(diviser(10, 0))

Il produit :

Résultat
Traceback (most recent call last):
  File "exemple.py", line 5, in <module>
    print(diviser(10, 0))
  File "exemple.py", line 2, in diviser
    return a / b
ZeroDivisionError: division by zero
  • La dernière ligne donne le type d'erreur et son explication : ZeroDivisionError: division by zero (« division par zéro »). C'est ce qu'il faut lire en premier ;
  • les lignes au-dessus racontent le chemin parcouru, de l'appel initial (ligne 5) jusqu'à l'instruction qui a planté (ligne 2, dans diviser) ;
  • les numéros de ligne te disent où regarder.

En JavaScript, le principe est le même : la première ligne du message donne le type et l'explication, par exemple TypeError: Cannot read properties of undefined (reading 'length') (on a demandé la taille de quelque chose qui n'existe pas), suivie du chemin parcouru.

Ne traduis pas mot à mot : repère le type (TypeError, KeyError...) et l'objet concerné (undefined, 'kiwi'...). Et si tu ne comprends pas, copie le message dans un moteur de recherche : des milliers de personnes l'ont déjà eu avant toi.

La méthode en quatre étapes

Quand le résultat est faux, ne modifie pas le code au hasard. Procède dans l'ordre :

  1. Reproduis le problème avec le plus petit exemple possible (une liste de 3 notes, pas de 300).
  2. Prédis ce que le programme devrait afficher, en le calculant à la main. Sans cette prédiction, tu ne sais pas où est l'écart.
  3. Observe : affiche les valeurs intermédiaires avec console.log ou print pour voir à quel moment le programme s'écarte de ta prédiction.
  4. Une hypothèse, une modification, un test. Change une seule chose à la fois, relance, et regarde si cela a corrigé le problème.

Quand tu es vraiment bloqué·e, essaie d'expliquer ton code à voix haute, ligne par ligne, à quelqu'un (ou à un canard en plastique : c'est une vraie technique). Très souvent, la réponse apparaît pendant que tu parles.

Un exemple pas à pas : une moyenne qui se trompe

Cette fonction doit calculer la moyenne d'une liste de notes. Pour [12, 15, 9, 18], elle devrait renvoyer 13.5. Elle renvoie autre chose :

JavaScript
function moyenne(notes) {
  let somme = 0;
  for (const note of notes) {
    somme = somme + note;
    return somme / notes.length;
  }
}

console.log(moyenne([12, 15, 9, 18]));
Python
def moyenne(notes):
    somme = 0
    for note in notes:
        somme = somme + note
        return somme / len(notes)


print(moyenne([12, 15, 9, 18]))

Le programme affiche 3 (ou 3.0 en Python). Aucune erreur : c'est donc une erreur de logique. Appliquons la méthode.

  1. Reproduire : on a déjà un petit exemple, 4 notes.
  2. Prédire : la somme vaut 12 + 15 + 9 + 18 = 54, et 54 / 4 = 13.5. On attend 13.5, on obtient 3 : c'est 12 / 4, soit la première note seulement divisée par 4.
  3. Observer : ajoutons un affichage dans la boucle, juste après le calcul de la somme :
JavaScript
console.log("tour", note, somme);
Python
print("tour", note, somme)

On voit s'afficher tour 12 12, et une seule fois. La boucle ne fait qu'un tour : elle s'arrête après la note 12.

  1. Hypothèse : quelque chose arrête la boucle trop tôt. Qu'est-ce qui sort d'une fonction ? return. Il est à l'intérieur de la boucle : au premier tour, la fonction renvoie 12 / 4 et s'arrête. On le sort de la boucle, en le décalant vers la gauche pour qu'il s'exécute après la boucle :
JavaScript
function moyenne(notes) {
  let somme = 0;
  for (const note of notes) {
    somme = somme + note;
  }
  return somme / notes.length;
}
Python
def moyenne(notes):
    somme = 0
    for note in notes:
        somme = somme + note
    return somme / len(notes)

On relance : 13.5. Bug trouvé, par méthode et pas par chance.

À retenir

  • Trois sortes d'erreurs : syntaxe (le programme ne démarre pas), exécution (il plante en route), logique (il tourne mais le résultat est faux).
  • Lis un message d'erreur par la fin : type et explication, puis le numéro de ligne.
  • La méthode : reproduire petit, prédire le bon résultat, observer avec des affichages, une hypothèse et une modification à la fois.
  • Les erreurs de logique sont les plus dures : il faut savoir ce qu'on attend, donc calcule le résultat à la main.

Quiz

Question 1. Classe chaque situation : erreur de syntaxe, d'exécution ou de logique ?

  • a. Tu as oublié de fermer une parenthèse : le programme ne démarre pas.
  • b. Le programme affiche 15 alors que le résultat devrait être 50, sans aucun message.
  • c. Le programme démarre puis s'arrête à la ligne 8 avec ZeroDivisionError.

Question 2. Un programme affiche un total faux, sans message d'erreur. Quelle est la meilleure première étape ?

  • A. Le relancer plusieurs fois en espérant que le résultat change.
  • B. Calculer à la main le résultat attendu, puis afficher les valeurs intermédiaires pour voir où le programme s'en écarte.
  • C. Tout réécrire depuis le début.

Question 3. Rappel du chapitre sur les boucles : ton programme semble figé et ne s'arrête jamais. Quelle est la cause la plus probable ?

Question 4. Rappel du chapitre sur les listes : en Python, ton programme plante avec IndexError: list index out of range. De quelle sorte d'erreur s'agit-il, et quelle en est la cause la plus fréquente ?

Code à corriger

Cette fonction calcule les frais de livraison : gratuite dès 40 €, sinon 4,90 €. Elle contient deux bugs, qui viennent de chapitres différents. Trouve-les avec la méthode du chapitre, en les corrigeant un par un.

Ces appels doivent donner : fraisDeLivraison(39.99) → 4.9, fraisDeLivraison(40) → 0, fraisDeLivraison(80) → 0.

JavaScript
function fraisDeLivraison(total) {
  if (total > 40) {
    return 0;
  } else {
    console.log(4.9);
  }
}

console.log(fraisDeLivraison(39.99));
console.log(fraisDeLivraison(40));
console.log(fraisDeLivraison(80));
Python
def frais_de_livraison(total):
    if total > 40:
        return 0
    else:
        print(4.9)


print(frais_de_livraison(39.99))
print(frais_de_livraison(40))
print(frais_de_livraison(80))

Exercice

Ce n'est plus seulement du code à écrire : ici, tu vas écrire les tests d'abord, comme le font les développeurs.

Une année est bissextile si elle est divisible par 4, sauf si elle est divisible par 100, à moins qu'elle ne soit aussi divisible par 400. Écris une fonction estBissextile(annee) (est_bissextile(annee) en Python) qui renvoie vrai ou faux.

Avant d'écrire la fonction, prédis les résultats que tu dois obtenir, à la main :

  • 2024 : bissextile ;
  • 2023 : pas bissextile ;
  • 1900 : pas bissextile (divisible par 100, mais pas par 400) ;
  • 2000 : bissextile (divisible par 400) ;
  • 2100 : pas bissextile.

Écris ensuite la fonction et affiche son résultat pour chacune de ces années : les cinq doivent correspondre à tes prédictions. Si l'un ne correspond pas, c'est le moment d'appliquer la méthode.

Pour t'aider : le reste de la division s'obtient avec %, et tu as vu && / and et || / or au chapitre 4.

Corrigés

Question 1. a. Erreur de syntaxe (le programme ne démarre pas). b. Erreur de logique (il tourne, mais le résultat est faux). c. Erreur d'exécution (il démarre, puis plante).

Question 2 : B. Sans calcul préalable, tu ne sais pas ce que tu cherches. Relancer en espérant (A) ne change rien : le programme est déterministe. Tout réécrire (C) perd du temps et réintroduit souvent les mêmes erreurs.

Question 3. Une boucle infinie, très probablement parce qu'une variable de la condition n'est jamais modifiée dans la boucle (on a oublié i = i + 1).

Question 4. C'est une erreur d'exécution. La cause la plus fréquente est une erreur de décalage d'un cran (off-by-one) : la boucle ou l'indice va un élément trop loin (range(len(liste) + 1), ou un indice égal à la taille de la liste).

Code à corriger. Premier bug, la borne : total > 40 exclut 40, alors que la livraison doit être gratuite dès 40 € ; il faut >= (chapitre 4). Deuxième bug, le return oublié : dans la branche else, la fonction affiche 4.9 au lieu de le renvoyer, donc l'appel renvoie undefined / None (chapitre 6). Version corrigée :

JavaScript
function fraisDeLivraison(total) {
  if (total >= 40) {
    return 0;
  } else {
    return 4.9;
  }
}
Python
def frais_de_livraison(total):
    if total >= 40:
        return 0
    else:
        return 4.9

Les trois appels donnent maintenant 4.9, 0 et 0. Remarque que corriger un seul des deux bugs ne suffisait pas : avec un seul bug corrigé, le résultat restait faux. C'est ce qui rend les bugs multiples pénibles : on corrige un à la fois, en relançant les tests à chaque fois.

Exercice. Une solution :

JavaScript
function estBissextile(annee) {
  return (annee % 4 === 0 && annee % 100 !== 0) || annee % 400 === 0;
}

for (const annee of [2024, 2023, 1900, 2000, 2100]) {
  console.log(annee, estBissextile(annee));
}
Python
def est_bissextile(annee):
    return (annee % 4 == 0 and annee % 100 != 0) or annee % 400 == 0


for annee in [2024, 2023, 1900, 2000, 2100]:
    print(annee, est_bissextile(annee))

Le programme affiche vrai pour 2024 et 2000, faux pour 2023, 1900 et 2100, comme prévu. Lis la condition ainsi : « divisible par 4 et pas par 100, ou divisible par 400 ». Les parenthèses indiquent quel regroupement se fait en premier. Écrire les résultats attendus avant le code est ce qui t'a permis de savoir, à coup sûr, que ta fonction marche : c'est la base du développement piloté par les tests.

10. Projet : la caisse du petit magasin

Objectif : à la fin de ce projet, tu as écrit un programme complet qui lit un panier, calcule le total avec remise et livraison, et affiche un vrai ticket de caisse. Tu y as réutilisé les variables, les conditions, les boucles, les fonctions, les listes et les dictionnaires.

L'idée

Tu as construit ce petit magasin morceau par morceau : le prix d'un article, la remise, le total d'un panier, les fonctions, le catalogue. Il est temps de tout assembler. Contrairement aux exercices précédents, personne ne te dit quelle instruction écrire : tu as la liste de ce que le programme doit faire, à toi de choisir comment.

Laisse-toi un temps de lutte : c'est normal de bloquer, et c'est ce moment qui fait vraiment progresser. Si tu es vraiment coincé·e, regarde d'abord les indices, puis seulement ensuite le corrigé.

Le cahier des charges

Le ticket doit ressembler à ceci pour le panier de départ :

Résultat
===== PETIT MAGASIN =====
pomme x10 : 5.00 €
pain x5 : 6.00 €
lait x12 : 13.20 €
fromage x3 : 14.40 €
cafe x4 : 14.00 €
-------------------------
Sous-total : 52.60 €
Remise : -5.26 €
Livraison : offerte
À PAYER : 47.34 €

Les règles du magasin :

  • le catalogue : pomme 0,50 €, pain 1,20 €, lait 1,10 €, fromage 4,80 €, café 3,50 € ;
  • la remise : 10 % dès 50 € d'achats, 20 % dès 100 € (celle du chapitre 4) ;
  • la livraison : offerte dès 40 €, après remise ; sinon elle coûte 4,90 € ;
  • les prix sont affichés avec deux décimales.

Le panier de départ :

  • 10 pommes, 5 pains, 12 laits, 3 fromages, 4 cafés.

Les étapes

Avance dans l'ordre. Teste chaque étape avant de passer à la suivante : c'est la méthode du chapitre 9.

Étape 1 : les données. Écris le catalogue (un dictionnaire : nom de l'article → prix) et le panier (une liste de dictionnaires, un par ligne : nom et quantite).

Étape 2 : le sous-total d'une ligne. Écris une fonction qui reçoit une ligne du panier et renvoie son prix (prix du catalogue × quantité). Teste-la avec une ligne : 10 pommes doivent faire 5.

Étape 3 : le total du panier. Écris une fonction qui reçoit le panier et renvoie la somme des sous-totaux, avec une boucle et un accumulateur. Pour le panier de départ, tu dois trouver 52.6.

Étape 4 : la remise. Écris une fonction qui reçoit un total et renvoie le taux de remise (0, 0.1 ou 0.2). Teste-la avec les valeurs limites : 49.99, 50, 99.99 et 100.

Étape 5 : la livraison. Écris une fonction qui reçoit le total après remise et renvoie les frais de livraison (0 ou 4.9). Teste les valeurs limites 39.99 et 40.

Étape 6 : le ticket. Écris une fonction qui affiche le ticket en réutilisant toutes les précédentes : une ligne par article (boucle), puis le sous-total, la remise, la livraison et le montant à payer.

Un outil de plus : afficher deux décimales

Pour afficher 5.00 € plutôt que 5 €, on formate le nombre :

  • en JavaScript : prix.toFixed(2) renvoie un texte avec 2 décimales ;
  • en Python, dans une f-string : f"{prix:.2f}".

Par exemple, (5).toFixed(2) en JavaScript et f"{5:.2f}" en Python donnent tous les deux 5.00.

Indices

Ouvre-les un par un, et seulement si tu es bloqué·e sur l'étape correspondante.

  • Étape 2 : dans une ligne, ligne["nom"] (ou ligne.nom) donne le nom de l'article. Cherche ce nom dans le catalogue pour obtenir le prix.
  • Étape 3 : c'est le même schéma qu'au chapitre 5 (l'accumulateur) et qu'au chapitre 8 (le panier). Prépare total = 0 avant la boucle.
  • Étape 4 : tu as déjà écrit les conditions de la remise au chapitre 4. Pense à tester le cas le plus grand en premier.
  • Étape 5 : « dès 40 € » signifie >= 40, pas > 40 : relis le bug du chapitre 9.
  • Étape 6 : calcule d'abord total, puis remise = total * taux, puis apresRemise = total - remise, puis la livraison sur apresRemise. Le montant à payer est apresRemise + livraison.

Pour aller plus loin

Quand ton ticket est conforme, améliore-le, une idée à la fois :

  1. N'affiche la ligne « Remise » que s'il y a une remise. Sinon, le ticket affiche Remise : -0.00 €, ce qui est étrange.
  2. Gère un article inconnu : si le nom n'est pas dans le catalogue, n'arrête pas le programme ; ignore la ligne et affiche un message (chapitre 8).
  3. Teste un petit panier : 2 pommes et 1 pain. La livraison doit être de 4,90 € et il n'y a pas de remise : tu dois trouver 7,10 € à payer.
  4. Ajoute un jour de promotion : par exemple, une variable jourDePromo qui, quand elle est vraie, ajoute 5 % de remise.

Corrigé

Il y a mille façons de le faire. Voici une solution complète qui suit les étapes, avec la première amélioration (la ligne « Remise » n'apparaît que s'il y a une remise).

JavaScript
const catalogue = { pomme: 0.5, pain: 1.2, lait: 1.1, fromage: 4.8, cafe: 3.5 };

const panier = [
  { nom: "pomme", quantite: 10 },
  { nom: "pain", quantite: 5 },
  { nom: "lait", quantite: 12 },
  { nom: "fromage", quantite: 3 },
  { nom: "cafe", quantite: 4 },
];

function sousTotal(ligne) {
  return catalogue[ligne.nom] * ligne.quantite;
}

function totalPanier(panier) {
  let total = 0;
  for (const ligne of panier) {
    total = total + sousTotal(ligne);
  }
  return total;
}

function tauxRemise(total) {
  if (total >= 100) {
    return 0.2;
  } else if (total >= 50) {
    return 0.1;
  }
  return 0;
}

function fraisDeLivraison(total) {
  if (total >= 40) {
    return 0;
  }
  return 4.9;
}

function afficherTicket(panier) {
  console.log("===== PETIT MAGASIN =====");
  for (const ligne of panier) {
    console.log(
      `${ligne.nom} x${ligne.quantite} : ${sousTotal(ligne).toFixed(2)} €`,
    );
  }

  const total = totalPanier(panier);
  const remise = total * tauxRemise(total);
  const apresRemise = total - remise;
  const livraison = fraisDeLivraison(apresRemise);

  console.log("-------------------------");
  console.log(`Sous-total : ${total.toFixed(2)} €`);
  if (remise > 0) {
    console.log(`Remise : -${remise.toFixed(2)} €`);
  }
  if (livraison === 0) {
    console.log("Livraison : offerte");
  } else {
    console.log(`Livraison : ${livraison.toFixed(2)} €`);
  }
  console.log(`À PAYER : ${(apresRemise + livraison).toFixed(2)} €`);
}

afficherTicket(panier);
Python
catalogue = {"pomme": 0.5, "pain": 1.2, "lait": 1.1, "fromage": 4.8, "cafe": 3.5}

panier = [
    {"nom": "pomme", "quantite": 10},
    {"nom": "pain", "quantite": 5},
    {"nom": "lait", "quantite": 12},
    {"nom": "fromage", "quantite": 3},
    {"nom": "cafe", "quantite": 4},
]


def sous_total(ligne):
    return catalogue[ligne["nom"]] * ligne["quantite"]


def total_panier(panier):
    total = 0
    for ligne in panier:
        total = total + sous_total(ligne)
    return total


def taux_remise(total):
    if total >= 100:
        return 0.2
    elif total >= 50:
        return 0.1
    return 0


def frais_de_livraison(total):
    if total >= 40:
        return 0
    return 4.9


def afficher_ticket(panier):
    print("===== PETIT MAGASIN =====")
    for ligne in panier:
        print(f"{ligne['nom']} x{ligne['quantite']} : {sous_total(ligne):.2f} €")

    total = total_panier(panier)
    remise = total * taux_remise(total)
    apres_remise = total - remise
    livraison = frais_de_livraison(apres_remise)

    print("-------------------------")
    print(f"Sous-total : {total:.2f} €")
    if remise > 0:
        print(f"Remise : -{remise:.2f} €")
    if livraison == 0:
        print("Livraison : offerte")
    else:
        print(f"Livraison : {livraison:.2f} €")
    print(f"À PAYER : {apres_remise + livraison:.2f} €")


afficher_ticket(panier)

Ce que ce programme met en œuvre, chapitre par chapitre :

  • variables : total, remise, apresRemise, livraison ;
  • conditions : tauxRemise, fraisDeLivraison, l'affichage de la livraison offerte ;
  • boucles : le total du panier et l'affichage de chaque ligne ;
  • fonctions : chaque règle du magasin est une petite fonction qu'on peut tester seule ;
  • listes : le panier ;
  • dictionnaires : le catalogue, et chaque ligne du panier.

Pour la deuxième vérification (2 pommes et 1 pain), le ticket affiche un sous-total de 2.20 €, une livraison de 4.90 € et un total à payer de 7.10 €, sans ligne de remise.

Et maintenant ?

Si tu es arrivé·e jusqu'ici en ayant vraiment cherché les exercices, tu sais programmer : tu peux lire un programme simple, le suivre à la main, et en écrire un qui résout un problème concret. Les langages changeront, les idées, non.

Pour continuer, deux directions naturelles :

  • creuser un langage : les parcours JavaScript de zéro et Python pour débuter reprennent ces notions en profondeur, avec davantage d'exercices ;
  • comprendre ce qu'il y a sous le capot d'Internet : les modules sur les protocoles (le handshake TCP, HTTP...) expliquent comment deux ordinateurs se parlent, avec des schémas animés.

Reviens aussi dans quelques jours refaire les quiz de ce cours, sans regarder les corrigés : c'est la meilleure façon de ne pas oublier.