Première
Langages et programmation
Ce chapitre couvre les constructions élémentaires de la programmation : variables, conditions, boucles et fonctions, en Python.
Structures conditionnelles
Pourquoi des conditionnelles ?
Les instructions conditionnelles permettent, selon le résultat (vrai ou faux) d'une expression booléenne, d'exécuter un bloc d'instructions plutôt qu'un autre. C'est un élément fondamental de tout langage de programmation.
Syntaxe en Python
if condition:
# bloc execute si condition est vraie
...
else:
# bloc execute sinon
...Exemple. Tester si un entier est pair, en utilisant le reste de la division par 2 (n % 2) :
def suivant(u):
"""Renvoie le terme suivant dans la suite de Syracuse"""
if u % 2 == 0:
v = u // 2
else:
v = 3 * u + 1
return vConditions imbriquées et elif
Il est possible d'imbriquer des conditions. Pour éviter trop de blocs imbriqués (peu lisibles), Python propose le mot-clé elif (contraction de else if).
Exemple. Une année est bissextile si elle est divisible par 400, ou si elle est divisible par 4 sans être divisible par 100 :
def bissextile(a):
if a % 400 == 0:
resultat = True
elif a % 100 == 0:
resultat = False
elif a % 4 == 0:
resultat = True
else:
resultat = False
return resultatUn seul des quatre blocs est exécuté (le premier dont la condition est vérifiée), ce qui permet de vérifier facilement la fonction avec des tests :
assert bissextile(1984)
assert bissextile(2000)
assert not bissextile(1982)
assert not bissextile(2100)Exercice — Tester une fonction avec assert
Écrire une fonction signe(x) qui renvoie la chaîne "positif" si , "negatif" si , et "nul" si . Écrire ensuite trois instructions assert pour vérifier votre fonction.
Exercice — TP Python 1ère — vitesse moyenne et classification du mode de déplacement
Écris un programme Python qui :
- demande à l'utilisateur de saisir une distance parcourue en kilomètres, puis un temps de trajet en heures ;
- calcule la vitesse moyenne correspondante (en km/h) ;
- affiche cette vitesse moyenne arrondie à deux décimales ;
- indique, selon la vitesse moyenne obtenue, le mode de déplacement le plus probable, avec les seuils suivants :
- à pied si km/h ;
- à vélo si km/h ;
- en voiture si km/h.
Exercice — TP Python 1ère — multiple de deux autres nombres et mention selon un score
Partie A. Écris un programme Python qui lit trois nombres entiers non nuls saisis par l'utilisateur, et affiche "oui" si l'un des trois est un multiple exact des deux autres à la fois, "non" sinon.
Partie B. Écris un programme Python qui saisit un entier s représentant un score, et qui affiche :
"Échec"si ,"Moyen"si ,"Bien"si ,"Excellent"si .
Exercice — Une calculatrice et un jury d'examen
D'après des fiches d'exercices de NSI Première.
1. Calculatrice. L'utilisateur saisit deux nombres et une opération (+, -, * ou /). Le programme affiche le calcul et son résultat avec quatre décimales, par exemple :
Nombre 1 : 13.2
Opération (+, -, * ou /) : /
Nombre 2 : 3
13.2000 / 3.0000 = 4.4000Prévoir les cas d'une opération inconnue et d'une division par zéro.
2. Jury d'examen. Un candidat passe trois épreuves. Il est admis :
- soit s'il a obtenu au moins 9 à chacune des trois épreuves ;
- soit si la moyenne de ses trois notes est au moins égale à 10 et que sa plus basse note est au moins égale à 8.
Sinon, il est refusé. Écrire un programme qui fait saisir le nom du candidat et ses trois notes, puis affiche la décision. Que décide le jury pour un candidat ayant obtenu 10,5 ; 7 et 12 ? Et pour 8 ; 12 et 11 ?
Exercice — Premiers programmes : division entière, modulo et échange de variables
D'après des séries d'exercices de NSI Première.
- Durée. Écrire un programme qui demande un nombre de minutes et l'affiche en heures et minutes : 135 minutes donnent « 2 heures et 15 minutes ».
- Parité. Écrire un programme qui demande un entier et affiche s'il est pair ou impair.
- Échange. On saisit deux valeurs
aetb. Échanger leurs contenus, puis les afficher : aveca = 5etb = 3, on doit obtenira = 3etb = 5. Pourquoi les deux instructionsa = bpuisb = ane conviennent-elles pas ? - Température. Convertir en degrés Fahrenheit une température saisie en degrés Celsius, avec . Que donnent 37 °C ? −40 °C ?
- Âge. Demander son âge à l'utilisateur et afficher son année de naissance, en supposant que l'on est en 2024. Pourquoi le résultat peut-il être faux d'un an ?
Exercice — Années bissextiles, tri de trois nombres et tranches d'impôt
D'après des séries d'exercices de NSI Première.
- Année bissextile. Une année est bissextile si elle est divisible par 4 mais pas par 100, sauf si elle est divisible par 400. Écrire une fonction
bissextile(annee)qui renvoie un booléen, et la tester sur 2024, 2023, 1900 et 2000. - Trois nombres. Écrire une fonction
trier3(a, b, c)qui renvoie les trois nombres rangés du plus petit au plus grand, sans utilisersorted,sort,minnimax. - Appréciation. Écrire une fonction qui renvoie l'appréciation d'une note sur 20 : « Insuffisant » en dessous de 10, « Assez bien » de 10 inclus à 15 exclu, « Bien » de 15 inclus à 18 exclu, « Excellent » à partir de 18.
- Impôt. Un barème indique : pas d'impôt en dessous de 10 000 € de revenu annuel ; 10 % entre 10 000 € et 25 000 € ; 20 % au-delà de 25 000 €.
- a. On l'interprète d'abord ainsi : on repère la tranche du revenu, puis on applique son taux au revenu entier. Écrire la fonction
impot(revenu)correspondante. Calculer l'impôt pour 25 000 € puis pour 25 001 €. Que constate-t-on ? - b. Dans un barème progressif, chaque taux ne s'applique qu'à la part du revenu située dans sa tranche. Écrire
impot_progressif(revenu)et calculer l'impôt pour 20 000 € et pour 30 000 €.
- a. On l'interprète d'abord ainsi : on repère la tranche du revenu, puis on applique son taux au revenu entier. Écrire la fonction
Exercice — Mini-projet : pierre, feuille, ciseaux
D'après des séries d'exercices de NSI Première.
Au jeu de pierre-feuille-ciseaux, la pierre bat les ciseaux, les ciseaux battent la feuille, et la feuille bat la pierre ; deux coups identiques donnent une égalité.
- Écrire une fonction
gagnant(coup1, coup2)qui renvoie1si le premier coup gagne,2si le second gagne,0en cas d'égalité. Les coups sont les chaînes"pierre","feuille"et"ciseaux". - Écrire un programme qui fait jouer l'utilisateur contre l'ordinateur, qui choisit son coup au hasard, en cinq manches, puis affiche le score final.
QCM — Structures conditionnelles
Boucles bornées et non bornées
Boucle bornée : for
Lorsque le nombre de répétitions est connu à l'avance, on utilise une boucle bornée, la boucle for.
for i in range(n):
instruction1
instruction2Sémantique. La variable i prend successivement les valeurs . Pour chacune de ces valeurs, les instructions du corps de la boucle sont exécutées.
Exemple. Afficher la table de multiplication d'un nombre :
def table(nombre):
"""Affiche la table de multiplication de 'nombre', de 0 a 10."""
for i in range(11):
print(i, "x", nombre, "=", i * nombre)On peut aussi utiliser for pour parcourir une chaîne de caractères, terme à terme :
def nombre_de_voyelles(mot):
"""Renvoie le nombre de voyelles dans 'mot' (suppose en minuscules)."""
voyelles = "aeiouy"
compteur = 0
for lettre in mot:
if lettre in voyelles:
compteur = compteur + 1
return compteur
assert nombre_de_voyelles("programmation") == 5Boucle non bornée : while
Lorsque le nombre de répétitions n'est pas connu à l'avance, mais dépend de la vérification d'une condition, on utilise une boucle non bornée, la boucle while.
while condition:
instruction1
instruction2Sémantique. La condition est évaluée : si elle est vraie, le corps de la boucle est exécuté puis on revient tester la condition ; si elle est fausse, on sort de la boucle.
Attention aux boucles infinies ! Une boucle while correctement construite comporte trois éléments :
- une initialisation avant d'entrer dans la boucle ;
- un test qui détermine si l'on continue ou si l'on s'arrête ;
- une instruction qui modifie, à chaque tour, une variable utilisée dans le test.
Exemple. Un capital placé augmente de 5 % chaque année (il est multiplié par 1,05). On veut savoir au bout de combien d'années il dépasse un certain seuil :
def duree_pour_atteindre(capital_depart, seuil):
"""
Precondition : capital_depart > 0 et seuil > capital_depart
Resultat : nombre d'annees necessaires pour que le capital,
qui augmente de 5 % chaque annee, depasse 'seuil'
"""
annee = 0 # 1. initialisation
capital = capital_depart
while capital < seuil: # 2. test
capital = capital * 1.05 # 3. modification de la variable testee
annee = annee + 1
return annee
assert duree_pour_atteindre(120, 500) == 30Quelle boucle choisir ?
| Situation | Boucle adaptée |
|---|---|
| On connaît à l'avance le nombre de répétitions (parcourir une liste, une chaîne, un intervalle d'entiers) | for |
| Le nombre de répétitions dépend d'une condition qu'on ne peut pas calculer avant de commencer (attendre une saisie valide, itérer jusqu'à ce qu'un seuil soit dépassé) | while |
Complément. Dans une boucle, l'instruction break interrompt immédiatement la boucle, et continue passe directement au tour suivant sans exécuter le reste du corps de la boucle.
Exercice — Somme des n premiers entiers : for et while
- Écrire une fonction
somme_for(n)qui calcule à l'aide d'une bouclefor. - Écrire une fonction
somme_while(n)qui calcule le même résultat à l'aide d'une bouclewhile. - Vérifier que
somme_for(10)etsomme_while(10)renvoient bien .
Exercice — TP Python 1ère — somme des N premiers nombres impairs (boucle for et boucle while) et test de tri décroissant
Partie A/B. Écris un programme qui demande à l'utilisateur de saisir un nombre entier positif N, calcule la somme des N premiers nombres impairs () une première fois à l'aide d'une boucle for i in range(...), puis une seconde fois à l'aide d'une boucle while, et affiche les deux résultats.
Partie C. Écris une fonction est_decroissant(T) qui prend une liste T en entrée et retourne True si ses éléments sont triés en ordre strictement décroissant, False sinon.
Exemples : est_decroissant([9, 7, 5, 3, 1]) doit renvoyer True ; est_decroissant([10, 8, 6, 7, 4]) doit renvoyer False.
Exercice — QCM de devoir : boucles et condition de sortie
D'après un devoir surveillé de NSI Première (2020-2021).
Pour chaque question, une seule proposition est exacte.
Question 1. Quelle valeur affiche ce programme ?
x = 1
for i in range(10):
x = x * 2
print(x)A. 1024 — B. 2 — C. 20000000000 — D. 2048
Question 2. On veut afficher tous les nombres pairs de 0 à 152. Par quoi remplacer la ligne en pointillés ?
n = 0
......................
print(n)
n = n + 2A. for i in range(152): — B. for n in range(153): — C. while n <= 152: — D. while n < 151:
Question 3. On considère la fonction suivante, où capital et interet sont des nombres strictement positifs.
def capital_double(capital, interet):
n = 0
montant = capital
while montant <= 2 * capital:
montant = montant + interet
n = n + 1
return nQue peut-on toujours affirmer à propos du nombre n renvoyé ?
A. capital * n * interet > 2 * capital
B. n == 2 * capital / interet
C. capital + n * interet > 2 * capital
D. n == capital / interet
Exercice — Compléter un test de primalité avec une boucle while
D'après un devoir surveillé de NSI Première (2020-2021).
La fonction suivante doit indiquer si un entier a supérieur à 2 est premier, ou bien afficher l'un de ses diviseurs.
from math import sqrt
def premier(a):
i = 2
while a % i != 0:
i = i + 1
if i > sqrt(a):
print(...)
i = a
if ...:
print("Le nombre", a, "est divisible par", i)- À quoi sert la boucle
while(lignewhile a % i != 0:) ? - Compléter l'instruction
print(...). - Compléter la condition
if ...:de l'avant-dernière ligne. - Dérouler l'appel
premier(9), puis l'appelpremier(7).
Exercice — Tables de multiplication et triangles d'étoiles
D'après des fiches d'exercices de NSI Première.
1. Écrire un programme qui fait saisir un entier naturel n, puis affiche sa table de multiplication de 0 à 11, sous la forme 0 * 17 = 0, 1 * 17 = 17, etc.
2. Écrire un programme qui réalise l'affichage suivant :
*****
****
***
**
*3. Écrire un programme qui fait saisir un entier N supérieur ou égal à 2, puis affiche un triangle « vide » de hauteur N. Pour N = 5 :
*
**
* *
* *
*****Exercice — Saisie avec valeur sentinelle et analyse d'un texte
D'après des séries d'exercices de NSI Première.
- Valeur sentinelle. Écrire un programme qui fait saisir des notes, entre 0 et 20, sans savoir à l'avance combien il y en aura. La saisie s'arrête quand l'utilisateur entre −1 ; une note hors de l'intervalle est refusée. Le programme affiche alors la moyenne des notes saisies. Pourquoi faut-il ici une boucle
while? Quel cas particulier faut-il traiter ? - Analyse d'un texte. Écrire un programme qui fait saisir une phrase, puis affiche son nombre de mots, son nombre de voyelles et son mot le plus long. Que donne-t-il pour « Le petit chat dort sur le canapé » ?
Exercice — Épreuve pratique NSI 2024 — Sujet 12, exercice 2 : jeu du plus ou moins
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°12, exercice 2.
Le jeu du « plus ou moins » consiste à deviner un nombre entier choisi entre 1 et 99. Une élève de NSI décide de le coder en langage Python de la manière suivante :
- le programme génère un nombre entier aléatoire compris entre 1 et 99 ;
- si la proposition de l'utilisatrice est plus petite que le nombre cherché, l'utilisatrice en est avertie ; elle peut alors en tester un autre ;
- si la proposition de l'utilisatrice est plus grande que le nombre cherché, l'utilisatrice en est avertie ; elle peut alors en tester un autre ;
- si l'utilisatrice trouve le bon nombre en 10 essais ou moins, elle gagne ;
- si l'utilisatrice a fait plus de 10 essais sans trouver le bon nombre, elle perd.
La fonction randint est utilisée : si a et b sont des entiers tels que a <= b, randint(a, b) renvoie un nombre entier compris entre a et b inclus.
Compléter le code ci-dessous et le tester :
from random import randint
def plus_ou_moins():
nb_mystere = randint(1, ...)
nb_test = int(input("Proposez un nombre entre 1 et 99 : "))
compteur = ...
while nb_mystere != ... and compteur < ...:
compteur = compteur + 1
if nb_mystere ... nb_test:
nb_test = int(input("Trop petit ! Testez encore : "))
else:
nb_test = int(input("Trop grand ! Testez encore : "))
if nb_mystere == nb_test:
print ("Bravo ! Le nombre était ", ...)
print("Nombre d'essais: ", ...)
else:
print ("Perdu ! Le nombre était ", ...)Créez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2024 — Sujet 18, exercice 1 : multiplier avec des additions
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°18, exercice 1.
Programmer la fonction multiplication qui prend en paramètres deux nombres entiers relatifs n1 et n2, et qui renvoie le produit de ces deux nombres.
Les seules opérations arithmétiques autorisées sont l'addition et la soustraction.
Exemples :
>>> multiplication(3, 5)
15
>>> multiplication(-4, -8)
32
>>> multiplication(-2, 6)
-12
>>> multiplication(-2, 0)
0Créez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2024 — Sujet 19, exercice 1 : listes de puissances d'un entier
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°19, exercice 1.
On rappelle que :
- le nombre est le nombre , où le facteur apparaît fois ;
- en langage Python, l'instruction
t[-1]permet d'accéder au dernier élément du tableaut.
Dans cet exercice, l'opérateur ** et la fonction pow ne sont pas autorisés.
Programmer en langage Python une fonction liste_puissances qui prend en argument un nombre entier , un entier strictement positif et qui renvoie la liste de ses puissances .
Programmer également une fonction liste_puissances_borne qui prend en argument un nombre entier supérieur ou égal à 2 et un entier borne, et qui renvoie la liste de ses puissances, à l'exclusion de , strictement inférieures à borne.
Exemples :
>>> liste_puissances(3, 5)
[3, 9, 27, 81, 243]
>>> liste_puissances(-2, 4)
[-2, 4, -8, 16]
>>> liste_puissances_borne(2, 16)
[2, 4, 8]
>>> liste_puissances_borne(2, 17)
[2, 4, 8, 16]
>>> liste_puissances_borne(5, 5)
[]Créez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2024 — Sujet 26, exercice 2 : simuler un jeu de plateau
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°26, exercice 2.
On considère une piste carrée qui contient 4 cases par côté. Les cases sont numérotées de 0 inclus à 12 exclu comme ci-dessous :
+----+----+----+----+
| 0 | 1 | 2 | 3 |
+----+----+----+----+
| 11 | | 4 |
+----+ +----+
| 10 | | 5 |
+----+----+----+----+
| 9 | 8 | 7 | 6 |
+----+----+----+----+L'objectif de l'exercice est d'implémenter le jeu suivant :
Au départ, le joueur place son pion sur la case 0. À chaque coup, il lance un dé équilibré à six faces et avance son pion d'autant de cases que le nombre indiqué par le dé (entre 1 et 6 inclus) dans le sens des aiguilles d'une montre.
Par exemple, s'il obtient 2 au premier lancer, il pose son pion sur la case 2 puis s'il obtient 6 au deuxième lancer, il le pose sur la case 8, puis s'il obtient à nouveau 6, il pose le pion sur la case 2.
Le jeu se termine lorsque le joueur a posé son pion sur toutes les cases de la piste.
Compléter la fonction nombre_coups ci-dessous de sorte qu'elle renvoie le nombre de lancers aléatoires nécessaires pour terminer le jeu.
Proposer ensuite quelques tests pour en vérifier le fonctionnement.
from random import randint
def nombre_coups():
'''Simule un jeu de plateau avec 12 cases et renvoie le nombre
minimal de coups pour visiter toutes les cases.'''
nombre_cases = 12
# indique si une case a été vue
cases_vues = [ False ] * nombre_cases
nombre_cases_vues = 1
cases_vues[0] = True
case_en_cours = 0
n = ...
while ... < ...:
x = randint(1, 6)
case_en_cours = (case_en_cours + ...) % ...
if ...:
cases_vues[case_en_cours] = True
nombre_cases_vues = ...
n = ...
return nCréez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2024 — Sujet 33, exercice 1 : renverser une chaîne de caractères
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°33, exercice 1.
Programmer une fonction renverse, prenant en paramètre une chaîne de caractères non vide mot et renvoie cette chaîne de caractères en ordre inverse.
Exemple :
>>> renverse("")
''
>>> renverse("abc")
'cba'
>>> renverse("informatique")
'euqitamrofni'Créez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2024 — Sujet 48, exercice 2 : suite « look and say »
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°48, exercice 2.
On considère dans cet exercice la suite de nombres suivante : 1, 11, 21, 1211, 111221, …
Cette suite est construite ainsi : pour passer d'une valeur à la suivante, on la lit et on l'écrit sous la forme d'un nombre. Ainsi, pour 1211 :
- on lit un 1, un 2, deux 1 ;
- on écrit donc en nombre 1 1, 1 2, 2 1 ;
- puis on concatène 111221.
Compléter la fonction nombre_suivant qui prend en entrée un nombre sous forme de chaîne de caractères et qui renvoie le nombre suivant par ce procédé, encore sous forme de chaîne de caractères.
def nombre_suivant(s):
'''Renvoie le nombre suivant de celui representé par s
en appliquant le procédé de lecture.'''
resultat = ''
chiffre = s[0]
compte = 1
for i in range(...):
if s[i] == chiffre:
compte = ...
else:
resultat += ... + ...
chiffre = ...
...
lecture_... = ... + ...
resultat += lecture_chiffre
return resultatExemples :
>>> nombre_suivant('1211')
'111221'
>>> nombre_suivant('311')
'1321'Créez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2026 — Sujet 17 : budget d'un club de handball
Banque nationale de sujets 2026 de l'épreuve pratique, sujet n°17 (situation d'évaluation d'une heure).
Budget d'un club de handball
Un club de handball professionnel souhaite mieux comprendre et gérer ses dépenses et recettes annuelles. Les dirigeants veulent identifier les postes de dépenses les plus importants et s'assurer de l'exactitude de leur solde budgétaire de fin d'année.
On dispose de jeux de données sous forme de fichiers CSV représentant les mouvements budgétaires du club. Chaque mouvement est décrit par un enregistrement comportant les attributs suivants :
'type': chaîne de caractères dont les valeurs possibles sont'dépense'ou'recette';'catégorie': chaîne de caractères dont les valeurs possibles sont'subventions','sponsoring','billetterie','marketing','salaires','déplacements','fonctionnement','cotisations'ou'autres_charges';'montant': nombre flottant positif représentant la somme en euros ;'mois': nombre entier compris entre 1 et 12.
Une fois chargés par le script analyse_budget.py, ces jeux de données donnent une liste de dictionnaires mouvements. Deux jeux de données sont fournis :
- un jeu de test défini directement dans le code dans la variable
mouvements_test; - un jeu complet
budget_complet.csvde plus de 2 000 mouvements.
Le fichier analyse_budget.py contient plusieurs fonctions d'analyse que le sujet vise à compléter.
Question 1. Écrire la fonction total_par_type(mouvements, type_mouvement) qui prend en paramètres une liste de mouvements et une chaîne de caractères (parmi 'dépense' ou 'recette'). Cette fonction doit renvoyer la somme totale des montants correspondant à ce type précis. La fonction renverra 0 si aucun mouvement ne correspond. Créer ensuite une fonction test_total() contenant au moins deux assertions pour valider le bon fonctionnement de votre code sur le jeu de données mouvements_test (par exemple, le total des recettes attendu est de 2300.0).
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
La fonction solde_annuel(mouvements), déjà codée dans le fichier fourni, est censée calculer le bilan financier de l'année en faisant la somme des soldes de chaque mois (recettes totales moins dépenses totales). Si le solde annuel est positif, le club dégage des bénéfices. S'il est négatif, le club est en déficit.
Question 2. Calculer manuellement le solde annuel attendu pour la liste mouvements_test. Écrire ensuite une fonction test_solde_annuel() contenant une assertion qui vérifie que la fonction solde_annuel(mouvements_test) renvoie bien ce résultat théorique. Exécuter ce test.
L'exécution du test précédent lève une erreur : le résultat renvoyé par la fonction solde_annuel ne correspond pas à la réalité comptable.
Question 3. Analyser le code de la fonction solde_annuel pour identifier la source de cette erreur logique, expliquer pourquoi certains mouvements ont été ignorés, puis proposer une correction. Appliquer ensuite votre fonction corrigée sur le fichier budget_complet.csv pour annoncer le véritable solde du club au professeur.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Fichiers fournis
Le dossier comporte une version PDF de l'énoncé, le code source à analyser et compléter analyse_budget.py et le jeu de données complet budget_complet.csv (2 026 mouvements).
analyse_budget.py
import csv
def lire_mouvements_depuis_csv(nom_fichier_csv):
"""
Lit les données d'un fichier CSV et les retourne en liste de dictionnaires.
Les colonnes 'montant' et 'mois' sont converties respectivement en flottant et en entier.
"""
mouvements_csv = []
try:
with open(nom_fichier_csv, mode='r', newline='', encoding='utf-8') as fichier_csv:
lecteur_csv = csv.DictReader(fichier_csv)
for ligne in lecteur_csv:
ligne['montant'] = float(ligne['montant'])
ligne['mois'] = int(ligne['mois'])
mouvements_csv.append(ligne)
return mouvements_csv
except FileNotFoundError:
print(f"Erreur : Le fichier '{nom_fichier_csv}' est introuvable.")
return []
mouvements_test = [
{'type': 'recette', 'catégorie': 'cotisations', 'montant': 1200.0, 'mois': 1},
{'type': 'recette', 'catégorie': 'billetterie', 'montant': 300.0, 'mois': 6},
{'type': 'dépense', 'catégorie': 'fonctionnement', 'montant': 450.0, 'mois': 6},
{'type': 'dépense', 'catégorie': 'déplacements', 'montant': 200.0, 'mois': 12},
{'type': 'dépense', 'catégorie': 'salaires', 'montant': 1500.0, 'mois': 12},
{'type': 'recette', 'catégorie': 'subventions', 'montant': 800.0, 'mois': 12}
]
#############################################################################
# Écrire ci-dessous la fonction total_par_type et ses tests (Question 1) #
#############################################################################
#############################################################################
# Fonctions de calcul du solde (Questions 2 et 3) #
#############################################################################
def solde_mensuel(mouvements, mois):
"""
Calcule le solde pour un mois donné (recettes - dépenses).
"""
total_recettes = 0
total_depenses = 0
for m in mouvements:
if m['mois'] == mois:
if m['type'] == 'recette':
total_recettes += m['montant']
else:
total_depenses += m['montant']
return total_recettes - total_depenses
def solde_annuel(mouvements):
"""
Calcule le solde annuel en additionnant les soldes de chaque mois.
"""
total = 0
# Parcourt les mois de l'année pour cumuler le bilan
for m in range(1, 12):
total = total + solde_mensuel(mouvements, m)
return total
#############################################################################
# Écrire ci-dessous la fonction test_solde_annuel (Question 2) #
#############################################################################
#############################################################################
# Programme principal pour analyser le fichier complet #
#############################################################################
# mouvements_complets = lire_mouvements_depuis_csv("budget_complet.csv")
# print("Le solde annuel sur le fichier complet est de :", solde_annuel(mouvements_complets))budget_complet.csv (début du fichier)
type,catégorie,montant,mois
dépense,autres_charges,269.87,1
dépense,autres_charges,165.32,1
dépense,autres_charges,320.95,1
dépense,autres_charges,259.87,1
dépense,autres_charges,100.52,1
...Créez un compte gratuit : votre première correction est offerte.
QCM — Boucles bornées et non bornées
Fonctions : définition, paramètres et valeur de retour
Pourquoi définir des fonctions ?
Écrire des fonctions rend un programme plus simple à comprendre, plus facile à tester et plus facile à modifier. Une fonction est utilisée comme une boîte noire : on lui fournit des valeurs (les paramètres) et elle renvoie un résultat.
Définir une fonction en Python
def nom_fonction(parametre1, parametre2):
"""Docstring : ce que fait la fonction."""
...
return resultat- Le mot-clé
defintroduit la définition, suivi du nom de la fonction et de ses paramètres formels entre parenthèses. - Le corps de la fonction est délimité par l'indentation (contrairement à d'autres langages qui utilisent des accolades, voir la notion suivante).
- L'instruction
returntermine immédiatement l'exécution de la fonction et renvoie la valeur qui la suit.
Exemple. Calculer un prix TTC (toutes taxes comprises) à partir d'un prix HT et d'un taux de TVA, avec des annotations de type (facultatives) :
def prix_ttc(prix_ht: float, taux_tva: float) -> float:
"""Calcule le prix TTC a partir du prix HT et du taux de TVA (en %)."""
return prix_ht * (1 + taux_tva / 100)
print(prix_ttc(200, 5.5)) # 211.0Paramètres et arguments
Les noms utilisés dans la définition (prix_ht, taux_tva) sont les paramètres formels. Lors de l'appel, les valeurs fournies (200, 5.5) sont les paramètres effectifs (ou arguments).
ttc1 = prix_ttc(200, 5.5) # ht = 200, tva = 5.5À noter. Les variables définies à l'intérieur d'une fonction (comme prix_ht) sont locales : elles n'existent que pendant l'exécution de la fonction et ne sont pas accessibles en dehors.
Valeur de retour et fonctions sans retour
Le résultat renvoyé par une fonction peut être réutilisé dans un calcul :
total = prix_ttc(200, 5.5) + prix_ttc(100, 20) # total vaut 331.0Une fonction qui n'a pas d'instruction return (ou qui exécute juste return sans valeur) renvoie automatiquement la valeur spéciale None : on parle parfois de procédure quand l'objectif est un effet (comme un affichage) plutôt qu'un résultat.
def afficher_bienvenue(prenom):
"""Affiche un message de bienvenue (ne renvoie rien)."""
print("Bienvenue,", prenom)
resultat = afficher_bienvenue("Sam")
print(resultat) # NoneUne fonction peut en appeler une autre
def mention(note):
"""Renvoie la mention associee a une note sur 20."""
if note >= 16:
return "Très bien"
elif note >= 14:
return "Bien"
elif note >= 12:
return "Assez bien"
else:
return "Passable"
def bulletin(controle, examen):
"""Calcule une moyenne ponderee (30 % controle, 70 % examen) et sa mention."""
moyenne = 0.3 * controle + 0.7 * examen
return moyenne, mention(moyenne)Exercice — Moyenne pondérée et mention
- Écrire une fonction
mention(note)qui renvoie la chaîne"Très bien"si ,"Bien"si ,"Assez bien"si , et"Passable"sinon. - Écrire une fonction
note_finale(controle, examen)qui calcule une moyenne pondérée ( pour le contrôle, pour l'examen) et renvoie à la fois la moyenne et sa mention (en appelantmention). - Tester
note_finale(10, 16): que renvoie-t-elle ?
Exercice — TP Python 1ère — fonction de calcul de la surface d'un carré
Écris une fonction surface_carre(c) qui calcule et retourne la surface d'un carré de côté c (formule ). Écris ensuite un programme principal qui demande à l'utilisateur de saisir la longueur du côté du carré, appelle la fonction surface_carre() pour calculer la surface, puis affiche le résultat.
Exercice — TP Python 1ère — décomposer et recomposer une liste de points 3D
On travaille avec des coordonnées représentées sous forme de tuples (x, y, z), correspondant à des points en 3D :
points3D = [(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)]- Écris une fonction
decompose(points)qui prend en paramètre une liste de tuples(x, y, z)et renvoie trois listes distinctesX,Y,Z. Exemple attendu :decompose(points3D)renvoieX=[1, 4, 7, 10],Y=[2, 5, 8, 11],Z=[3, 6, 9, 12]. - Écris une fonction
recompose(X, Y, Z)qui prend ces trois listes et les fusionne pour reconstruire la liste de tuples initiale. Exemple attendu :recompose(X, Y, Z)renvoie[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)].
Exercice — Six petites fonctions à écrire et à tester
D'après des séries d'exercices de NSI Première.
Écrire les fonctions suivantes, puis les tester sur des exemples bien choisis.
compter_voyelles(chaine)renvoie le nombre de voyelles de la chaîne, minuscules ou majuscules, accentuées ou non.est_palindrome(mot)renvoieTruesi le mot se lit de la même façon dans les deux sens, comme « radar » ou « kayak ».est_premier(n)renvoieTruesi l'entiernest premier, c'est-à-dire s'il a exactement deux diviseurs, 1 et lui-même.mot_le_plus_long(mots)renvoie le mot le plus long d'une liste non vide (le premier rencontré en cas d'égalité).mot_de_passe_valide(mdp)renvoieTruesi le mot de passe compte au moins 8 caractères et contient au moins un chiffre.factorielle(n)renvoie , avec la convention .
Exercice — Épreuve pratique NSI 2024 — Sujet 35, exercice 2 : nombres palindromes
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°35, exercice 2.
Un mot palindrome peut se lire de la même façon de gauche à droite ou de droite à gauche : kayak, radar, et non sont des mots palindromes.
De même certains nombres ont des écritures décimales qui sont des palindromes : 33, 121, 345543.
L'objectif de cet exercice est d'obtenir un programme Python permettant de tester si un nombre est un nombre palindrome.
Pour remplir cette tâche, on vous demande de compléter le code des trois fonctions ci-dessous qui s'appuient les unes sur les autres :
inverse_chaine: qui renvoie une chaîne de caractères inversée ;est_palindrome: qui teste si une chaîne de caractères est un palindrome ;est_nbre_palindrome: qui teste si un nombre est un palindrome.
Compléter le code des trois fonctions ci-dessous.
def inverse_chaine(chaine):
'''Retourne la chaine inversée'''
resultat = ...
for caractere in chaine:
resultat = ...
return resultat
def est_palindrome(chaine):
'''Renvoie un booléen indiquant si la chaine ch
est un palindrome'''
inverse = inverse_chaine(chaine)
return ...
def est_nbre_palindrome(nbre):
'''Renvoie un booléen indiquant si le nombre nbre
est un palindrome'''
chaine = ...
return est_palindrome(chaine)Exemples :
>>> inverse_chaine('bac')
'cab'
>>> est_palindrome('NSI')
False
>>> est_palindrome('ISN-NSI')
True
>>> est_nbre_palindrome(214312)
False
>>> est_nbre_palindrome(213312)
TrueCréez un compte gratuit : votre première correction est offerte.
QCM — Fonctions
Diversité des langages de programmation
Un même problème, plusieurs langages
Python n'est qu'un langage de programmation parmi beaucoup d'autres (JavaScript, Scratch, C, Java...). Comparer Python à un autre langage permet de repérer ce qui est commun à (presque) tous les langages de programmation, et ce qui est spécifique à chacun.
Exemple. La fonction table, qui affiche la table de multiplication d'un nombre, écrite en Python puis en JavaScript :
def table(nombre):
"""Affiche la table de multiplication du parametre 'nombre'."""
for i in range(11):
print(i * nombre)/* Affiche la table de multiplication du paramètre 'nombre' */
function table(nombre) {
var i;
for (i = 0; i < 11; i++) {
console.log(i * nombre);
}
}Et la même idée en pseudo-code, indépendant de tout langage :
Fonction table(nombre)
Pour i de 0 à 10
Afficher i * nombre
FinPour
FinFonction
Traits communs
Malgré des syntaxes différentes, les trois versions ci-dessus partagent les mêmes constructions élémentaires :
- une fonction, avec un nom et un paramètre ;
- une boucle bornée qui répète 11 fois la même opération ;
- une variable (
i/nombre) ; - une instruction d'affichage.
Ces notions (variable, condition, boucle, fonction) existent dans la quasi-totalité des langages de programmation, y compris dans les langages à blocs comme Scratch, où une boucle répéter ou un bloc si... alors jouent exactement le même rôle qu'un for ou un if, mais assemblés visuellement plutôt qu'écrits sous forme de texte.
Traits spécifiques à chaque langage
| Python | JavaScript | |
|---|---|---|
| Délimitation d'un bloc | indentation | accolades { } |
| Définir une fonction | def nom(...): | function nom(...) { } |
| Boucle bornée | for i in range(n): | for (i = 0; i < n; i++) { } |
| Afficher un résultat | print(...) | console.log(...) |
| Fin d'instruction | retour à la ligne | souvent un point-virgule ; |
| Déclaration de variable | aucun mot-clé nécessaire | var, let ou const |
Ces différences sont purement syntaxiques : elles ne changent pas ce que le programme calcule, seulement la façon de l'écrire. Un autre exemple de trait spécifique : Python utilise un typage dynamique (le type d'une variable n'est jamais déclaré, il est déduit de sa valeur), alors que d'autres langages comme Java exigent de déclarer le type de chaque variable.
Pourquoi c'est utile
Savoir repérer les traits communs permet, une fois qu'on maîtrise un premier langage (ici Python), de comprendre rapidement les grandes lignes d'un programme écrit dans un langage inconnu : on y reconnaît des variables, des conditions, des boucles, des fonctions — seule leur écriture change.
Exercice — Traduire une fonction Python vers un autre langage
On donne la fonction Python suivante :
def est_majeur(age):
"""Renvoie True si age est superieur ou egal a 18, False sinon."""
if age >= 18:
return True
else:
return False- Traduire cette fonction en JavaScript (mots-clés
function, accolades,return). - Traduire cette fonction en pseudo-code.
- Lister trois traits communs et deux traits spécifiques entre les trois versions.
Exercice — Traduire une fonction JavaScript vers Python et repérer une boucle non bornée
On donne la fonction JavaScript suivante :
function sommeJusqua(n) {
var somme = 0;
var i = 1;
while (i <= n) {
somme = somme + i;
i = i + 1;
}
return somme;
}- Que calcule cette fonction ? Dérouler l'exécution de
sommeJusqua(4)en indiquant les valeurs desommeetià chaque tour de boucle, jusqu'à l'arrêt. - Traduire cette fonction en Python (sans mot-clé
var, avec les deux-points et l'indentation attendus). - S'agit-il ici d'une boucle bornée ou d'une boucle non bornée ? Justifier en comparant avec la boucle
forutilisée dans le cours. - Citer un trait spécifique à JavaScript utilisé dans ce code et absent en Python (parmi ceux vus dans le cours).
Exercice — Identifier les constructions dans un pseudo-code et en Scratch
On donne l'algorithme suivant en pseudo-code, qui affiche si un nombre est pair ou impair :
Fonction parite(nombre)
Si nombre % 2 == 0 alors
Afficher "pair"
Sinon
Afficher "impair"
FinSi
FinFonction
- Traduire cet algorithme en Python.
- Scratch est un langage à blocs (vu dans le cours) : il n'y a pas de code textuel, on assemble des blocs visuels. Décrire, en une phrase pour chacun, les blocs Scratch qui joueraient le même rôle que la structure
Si ... alors ... Sinon ... FinSi, que le testnombre % 2 == 0, et que l'instructionAfficher. - À quoi correspond l'opération
%(modulo) sur les nombres7et2? Sur8et2? - Cet algorithme utilise-t-il une boucle ? Justifier en listant les constructions élémentaires réellement présentes, parmi : variable, condition, boucle, fonction, affichage.
QCM — Diversité des langages
Spécification : préconditions et postconditions
Spécifier une fonction avant de l'écrire
Spécifier une fonction, c'est décrire précisément ce qu'elle doit faire avant d'écrire son code : son nom, ses paramètres (avec leur type), ce qu'elle renvoie, et sous quelles conditions elle fonctionne correctement. On parle du prototype d'une fonction et de son contrat.
Un contrat de fonction comporte deux parties :
- la précondition : ce que l'on suppose vrai sur les arguments avant l'appel (par exemple, un entier doit être positif) ;
- la postcondition : ce que l'on garantit être vrai sur le résultat après l'exécution, si la précondition était respectée.
Prototyper une fonction en Python
On documente le contrat directement dans la docstring de la fonction :
def racine_carree_entiere(n: int) -> int:
"""
Precondition : n >= 0
Postcondition : le resultat r verifie r * r <= n < (r + 1) * (r + 1)
"""
...Ce prototype suffit à comprendre comment utiliser la fonction, sans même connaître son implémentation : on sait quel type d'argument fournir, et ce que l'on peut attendre du résultat.
Vérifier une précondition avec assert
Une fois le contrat écrit, on implémente la fonction. L'instruction assert permet de vérifier qu'une précondition est bien respectée ; si la condition est fausse, le programme s'arrête immédiatement avec une erreur (AssertionError), ce qui évite de calculer un résultat incohérent.
def racine_carree_entiere(n: int) -> int:
"""
Precondition : n >= 0
Postcondition : le resultat r verifie r * r <= n < (r + 1) * (r + 1)
"""
assert n >= 0, "n doit etre positif ou nul"
r = 0
while (r + 1) * (r + 1) <= n:
r = r + 1
return r
assert racine_carree_entiere(10) == 3 # 3*3=9 <= 10 < 16=4*4
assert racine_carree_entiere(16) == 4 # 4*4=16 <= 16 < 25=5*5Ici, les deux derniers assert ne vérifient pas la précondition mais servent à tester que la postcondition est bien vérifiée sur des exemples : c'est le sujet de la notion suivante.
Pourquoi spécifier avant de coder ?
- Cela force à réfléchir au problème avant de se lancer dans l'écriture du code.
- Cela permet à quelqu'un d'autre (ou à soi-même plus tard) d'utiliser la fonction sans en lire le code.
- Cela donne une base pour écrire des tests : on sait déjà ce que le résultat doit vérifier.
Exercice — Spécifier puis implémenter indice_du_maximum
On veut écrire une fonction qui renvoie l'indice de l'élément maximum d'une liste de nombres.
- Écrire le prototype de la fonction
indice_du_maximum(tab), avec sa précondition et sa postcondition, sous forme de docstring. - Implémenter la fonction en Python, en utilisant
assertpour vérifier la précondition. - Vérifier avec
assertqueindice_du_maximum([3, 7, 2, 7, 1])renvoie bien1(le premier indice où le maximum apparaît).
Exercice — Déduire un contrat à partir d'une fonction déjà écrite
On donne la fonction Python suivante, déjà implémentée mais sans aucune documentation :
def moyenne(notes):
total = 0
for note in notes:
total = total + note
return total / len(notes)- Que se passe-t-il si on appelle
moyenne([])(liste vide) ? Détailler précisément quelle opération pose problème, et quelle erreur Python génère. - En déduire une précondition raisonnable sur le paramètre
notes. - Écrire une postcondition qui décrit ce que renvoie la fonction (on pourra utiliser le vocabulaire « moyenne arithmétique »).
- Réécrire la fonction avec sa docstring (précondition et postcondition) et un
assertqui vérifie la précondition en tout début de fonction. - Avec la précondition ajoutée, que se passe-t-il désormais si on appelle
moyenne([])?
Exercice — Spécifier et implémenter une division euclidienne
On veut écrire une fonction division_entiere(a, b) qui calcule le quotient q et le reste r de la division euclidienne de a par b, pour a un entier positif ou nul et b un entier strictement positif. Elle doit renvoyer le couple (q, r).
- Rappeler la propriété mathématique qui définit le quotient et le reste d'une division euclidienne de
aparb(relation entrea,b,qetr, et encadrement der). - Écrire la précondition de
division_entiere(a, b)(deux conditions, une suraet une surb). - Écrire la postcondition, en utilisant la propriété rappelée à la question 1.
- Implémenter la fonction en Python sans utiliser les opérateurs
//et%(on utilisera une boucle qui soustraitbautant de fois que possible), avec unassertqui vérifie la précondition. - Dérouler l'exécution de
division_entiere(17, 5): donner la valeur deqetrà chaque tour de boucle, jusqu'à l'arrêt.
Exercice — Épreuve pratique NSI 2024 — Sujet 37, exercice 1 : moyenne et cas du tableau vide
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°37, exercice 1.
Programmer la fonction moyenne prenant en paramètre un tableau d'entiers tab (de type list) qui renvoie la moyenne de ses éléments si le tableau est non vide. Proposer une façon de traiter le cas où le tableau passé en paramètre est vide.
Dans cet exercice, on s'interdira d'utiliser la fonction Python sum.
Exemples :
>>> moyenne([5,3,8])
5.333333333333333
>>> moyenne([1,2,3,4,5,6,7,8,9,10])
5.5
>>> moyenne([])
# Comportement différent suivant le traitement proposé.Créez un compte gratuit : votre première correction est offerte.
QCM — Spécification
Mise au point : jeux de tests et bibliothèques
Construire un jeu de tests
Mettre au point un programme, c'est vérifier qu'il fonctionne correctement, notamment à l'aide d'un jeu de tests : un ensemble de cas, chacun vérifié par une instruction assert, qui compare le résultat obtenu au résultat attendu.
Un bon jeu de tests doit être représentatif : il doit couvrir non seulement des cas "normaux", mais aussi des cas limites (valeur minimale, liste vide, zéro, valeur négative...), qui sont souvent la source des erreurs de programmation.
Exemple. Tester une fonction qui détermine si un entier est premier :
def est_premier(n):
"""
Precondition : n est un entier >= 2
Postcondition : renvoie True si n est premier, False sinon
"""
assert n >= 2
for diviseur in range(2, n):
if n % diviseur == 0:
return False
return True
# Jeu de tests
assert est_premier(2) == True # cas limite : le plus petit nombre premier
assert est_premier(4) == False # nombre pair, compose "evident"
assert est_premier(9) == False # carre d'un nombre impair (cas piege : 9 = 3*3)
assert est_premier(17) == True # nombre premier "ordinaire"Le cas est_premier(9) est important : un diviseur impair comme est plus facile à "oublier" en écrivant une fonction que les diviseurs pairs. Un jeu de tests exhaustif sur un petit intervalle (par exemple tester tous les entiers de à ) permet d'être encore plus confiant dans le résultat.
Utiliser une bibliothèque standard
Plutôt que de tout réécrire soi-même, on peut utiliser des fonctions déjà écrites et regroupées dans des bibliothèques (ou modules). On importe un module avec le mot-clé import, puis on accède à ses fonctions avec la notation module.fonction(...).
Exemple avec le module math :
import math
print(math.sqrt(16)) # 4.0 (racine carree)
print(math.floor(4.7)) # 4 (partie entiere par defaut)
print(math.pi) # 3.141592653589793
help(math.sqrt) # affiche la documentation de la fonction sqrtExemple avec le module random :
import random
de = random.randint(1, 6) # entier aleatoire entre 1 et 6 inclus
tirage = random.random() # flottant aleatoire dans [0, 1[
carte = random.choice(["pique", "coeur", "carreau", "trefle"]) # element au hasardLire la documentation. Pour utiliser une fonction d'une bibliothèque, il n'est pas nécessaire de connaître son code : il suffit de lire sa documentation, qui décrit son rôle, ses paramètres et sa valeur de retour — exactement comme le prototype d'une fonction vu dans la notion précédente. On peut consulter la documentation officielle (docs.python.org) ou l'appeler directement en Python avec help(nom_fonction).
Tester une fonction qui utilise le hasard
Une fonction qui repose sur random ne renvoie pas toujours le même résultat : on ne peut donc pas tester une valeur exacte avec ==. On teste plutôt que le résultat respecte les propriétés attendues (type, intervalle...), éventuellement en répétant le test plusieurs fois :
def lancer_de():
"""Simule un lance de de a 6 faces : renvoie un entier entre 1 et 6."""
return random.randint(1, 6)
for _ in range(1000):
resultat = lancer_de()
assert 1 <= resultat <= 6 # on teste l'intervalle, pas une valeur preciseExercice — Jeu de tests et simulation d'un dé
- On donne la fonction
est_pair(n)suivante :
def est_pair(n):
"""Renvoie True si n est pair, False sinon."""
return n % 2 == 0Écrire un jeu de tests représentatif pour cette fonction (au moins 4 cas, en incluant des cas limites : zéro, un nombre négatif).
-
En utilisant le module
random, écrire une fonctionlancer_de()qui simule le lancer d'un dé à 6 faces (renvoie un entier entre 1 et 6). -
Écrire un test adapté à cette fonction (on ne peut pas tester une valeur exacte).
Exercice — Piéger un bug grâce à un jeu de tests représentatif
On donne la fonction suivante :
def est_positif(n):
"""Renvoie True si n est positif ou nul, False sinon."""
return n > 0- D'après la docstring, que doit renvoyer
est_positif(0)? - Écrire un jeu de tests représentatif pour cette fonction (au moins 4 cas, en incluant les cas limites
n = 0et un nombre négatif). - Exécuter mentalement chacun de vos tests. L'un d'eux échoue-t-il ? Si oui, lequel, et pourquoi ?
- Corriger la fonction pour qu'elle respecte sa docstring.
Exercice — Tester une fonction combinant hasard et bibliothèque math
On veut écrire une fonction distance_a_lorigine() qui tire au hasard un point de coordonnées entières (x, y), avec x et y compris entre -10 et 10 inclus, à l'aide du module random, puis renvoie la distance de ce point à l'origine, calculée avec le module math.
- Rappeler la formule mathématique de la distance d'un point à l'origine.
- Écrire la fonction
distance_a_lorigine(), en utilisantrandom.randintpour tirerxety, et une fonction du modulemathpour calculer la distance. - Pourquoi ne peut-on pas tester cette fonction avec un simple
assert distance_a_lorigine() == valeur_attendue? - Écrire un test adapté à cette fonction, portant sur des propriétés que le résultat doit toujours vérifier (on pourra s'aider de
math.sqrt(200), qui donne la distance maximale possible). - Le cours présente une autre fonction du module
random, différente derandint. Laquelle, et quelle différence avecrandint?
Exercice — Corriger les erreurs d'un jeu de devinette
D'après un devoir surveillé de NSI Première (2020-2021).
Le programme suivant doit faire deviner au joueur un entier choisi au hasard entre 0 et 100 inclus. Il contient quatre erreurs : trois l'empêchent de fonctionner, la quatrième lui fait afficher un message faux. Les trouver et les corriger.
from random import randint
def devine():
"""Jeu : deviner un entier choisi au hasard entre 0 et 100 inclus."""
nbOrdi = random.randint(0, 100)
nbJoueur = -1
gagne = False
# On redemande un nombre tant que la partie n'est pas gagnée
while gagne = False:
nbJoueur = int(input("Choisissez un nombre entre 0 et 100 : "))
if nbJoueur = nbOrdi:
print("Bravo, vous avez trouvé !")
gagne = True
elif nbJoueur < nbOrdi:
print("Trop petit")
else:
print("Trop grand")Exercice — Épreuve pratique NSI 2024 — Sujet 31, exercice 1 : multiplier avec des additions, et tester
Banque nationale de sujets 2024 de l'épreuve pratique, sujet n°31, exercice 1.
Programmer la fonction multiplication, prenant en paramètres deux nombres entiers relatifs n1 et n2, et qui renvoie le produit de ces deux nombres.
Les seules opérations autorisées sont l'addition et la soustraction.
>>> multiplication(3, 5)
15
>>> multiplication(-4, -8)
32
>>> multiplication(-2, 6)
-12
>>> multiplication(-2, 0)
0Créez un compte gratuit : votre première correction est offerte.
Exercice — Épreuve pratique NSI 2026 — Sujet 18 : températures océaniques en Polynésie
Banque nationale de sujets 2026 de l'épreuve pratique, sujet n°18 (situation d'évaluation d'une heure).
Températures océaniques en Polynésie
En Polynésie française, un réseau de bouées océanographiques mesure quotidiennement la température de surface de l'océan dans quatre archipels : Société, Tuamotu, Marquises et Australes. Ces données permettent de documenter le réchauffement climatique dans le Pacifique Sud. Vous êtes chargé(e) de développer des outils d'analyse pour traiter ces relevés et détecter les anomalies thermiques.
On vous fournit le fichier analyse_temperatures_polynesie.py dans lequel figurent les données à utiliser, ainsi que les fonctions à écrire, compléter ou corriger.
Question 1. Écrire une fonction temperature_moyenne(zone, donnees) qui :
- prend en paramètres une chaîne
zone(nom d'un archipel) et un tableaudonneesde dictionnaires représentant les relevés ; - renvoie la température moyenne (
float) pour cette zone ; - renvoie
Nonesi la zone n'a aucun relevé.
Exemple :
>>> donnees = [
{'date': '2020-01-15', 'zone': 'Societe', 'temperature': 28.5},
{'date': '2020-01-16', 'zone': 'Societe', 'temperature': 29.0},
{'date': '2020-01-15', 'zone': 'Tuamotu', 'temperature': 27.5}
]
>>> temperature_moyenne('Societe', donnees)
28.75
>>> temperature_moyenne('Marquises', donnees)
>>>Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Question 2. Écrire une fonction detecter_anomalies(zone, seuil, donnees) qui :
- prend en paramètres une zone, un seuil (
float) et la listedonnees; - calcule la température moyenne de la zone ;
- renvoie la liste des dates où la température s'écarte de plus de
seuildegrés (en valeur absolue, via la fonctionabs()) de cette moyenne ; - renvoie une liste vide si la zone n'existe pas.
Exemple avec la liste donnees_test fournie dans le script :
>>> detecter_anomalies('Societe', 1.0, donnees_test)
['2010-06-20', '2021-05-30']Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Dans le fichier analyse_temperatures_polynesie.py figure le code de la fonction evolution_par_decennie(zone, donnees) censée calculer l'évolution des températures moyennes par décennie (2010, 2020).
Question 3. Compléter les trois fonctions de test, situées à la fin du fichier, pour la fonction evolution_par_decennie en utilisant le jeu de données fourni :
test_zone_inexistante(): tester une zone qui n'existe pas ;test_une_seule_decennie(): tester une zone avec données sur une seule décennie ;test_plusieurs_decennies(): tester une zone avec données sur plusieurs décennies.
Vos tests doivent permettre d'identifier le bug présent dans le code.
Question 4. Après avoir identifié le bug grâce à vos tests, corriger la fonction evolution_par_decennie.
Appel professeur — Appeler le professeur pour lui présenter votre réponse ou en cas de difficulté.
Fichier fourni : analyse_temperatures_polynesie.py
# =================================================================================#
# Données de test
donnees_test = [
# Société - Données sur 2010 et 2020
{'date': '2010-01-15', 'zone': 'Societe', 'temperature': 27.0},
{'date': '2010-06-20', 'zone': 'Societe', 'temperature': 26.5},
{'date': '2011-03-10', 'zone': 'Societe', 'temperature': 27.5},
{'date': '2020-02-14', 'zone': 'Societe', 'temperature': 28.0},
{'date': '2020-08-22', 'zone': 'Societe', 'temperature': 28.5},
{'date': '2021-05-30', 'zone': 'Societe', 'temperature': 29.0},
# Tuamotu - Données sur 2010 et 2020
{'date': '2015-04-10', 'zone': 'Tuamotu', 'temperature': 26.8},
{'date': '2020-07-15', 'zone': 'Tuamotu', 'temperature': 27.5},
{'date': '2021-09-20', 'zone': 'Tuamotu', 'temperature': 28.0},
# Marquises - Données uniquement sur 2020
{'date': '2020-03-15', 'zone': 'Marquises', 'temperature': 25.5},
{'date': '2021-07-10', 'zone': 'Marquises', 'temperature': 26.0},
{'date': '2022-11-25', 'zone': 'Marquises', 'temperature': 26.5},
]
# =================================================================================#
# Question 1 : Ecrire le code de votre fonction température_moyenne
# =================================================================================#
# Question 2 : Ecrire le code de votre fonction detection_anomalies
# =================================================================================#
# code de la fonction evolution_par_decennie à corriger dans la question 4:
def evolution_par_decennie(zone, donnees):
"""
Calcule l'évolution des températures moyennes par décennie pour une zone.
ATTENTION: Cette fonction contient un bug volontaire à détecter et corriger.
Arguments:
zone (str): Nom de l'archipel (ex: 'Societe', 'Tuamotu')
donnees (list): Liste de dictionnaires de relevés
Renvoie:
dict: Dictionnaire {décennie : température_moyenne}
ex: {2010: 27.5, 2020: 28.3}
Renvoie un dictionnaire vide si la zone n'existe pas
"""
# Filtrage des relevés pour la zone
releves_zone = [r for r in donnees if r['zone'] == zone]
if len(releves_zone) == 0:
return {}
# Regroupement par décennie
temperatures_par_decennie = {}
for releve in releves_zone:
# Extraction de l'année de la date (format: 'YYYY-MM-DD')
annee = int(releve['date'].split('-')[0])
# Calcul de la décennie
decennie = (annee // 10)
if decennie not in temperatures_par_decennie:
temperatures_par_decennie[decennie] = []
temperatures_par_decennie[decennie].append(releve['temperature'])
# Calcul des moyennes
moyennes = {}
for decennie, temperatures in temperatures_par_decennie.items():
moyennes[decennie] = round(sum(temperatures) / len(temperatures), 2)
return moyennes
# =================================================================================#
# Exercice 2.1 :
"""
Tests
À compléter par le candidat dans le cadre de la question 3
"""
def test_zone_inexistante():
"""
Test 1 : Tester une zone qui n'existe pas
À compléter:
1. Appeler evolution_par_decennie avec une zone inexistante
2. Vérifier que le résultat est un dictionnaire vide
"""
pass # à remplacer par le code du candidat
def test_une_seule_decennie():
"""
Test 2: Tester une zone avec données sur une seule décennie
À compléter:
1. Appeler evolution_par_decennie avec la zone appropriée
2. Vérifier que le résultat ne contient qu'une seule décennie (2020)
3. Vérifier la température moyenne
"""
pass # à remplacer par le code du candidat
def test_plusieurs_decennies():
"""
Test 3 : Tester une zone avec données sur plusieurs décennies
À compléter:
1. Appeler evolution_par_decennie avec la zone appropriée
2. Vérifier que le résultat contient bien les clés 2010 et 2020
3. Vérifier que les températures moyennes sont cohérentes
"""
pass # à remplacer par le code du candidatCréez un compte gratuit : votre première correction est offerte.
QCM — Jeux de tests et bibliothèques
Exercices bilan
Afficher le niveau de charge d'une batterie
1. Lire une fonction. On considère la fonction suivante :
def niveau_batterie(pourcentage):
"""Renvoie le niveau de charge ('critique', 'faible', 'normale' ou 'pleine')
pour un pourcentage de batterie compris entre 0 et 100."""
if pourcentage <= 10:
niveau = "critique"
elif pourcentage <= 30:
niveau = "faible"
elif pourcentage <= 80:
niveau = "normale"
else:
niveau = "pleine"
return niveauDonner la valeur renvoyée par niveau_batterie(45) et par niveau_batterie(10), en précisant pour chacun des deux appels quelle est la première condition évaluée à True dans la chaîne if/elif/else.
2. Cas limites. Écrire un jeu de tests (sous forme d'instructions assert) qui vérifie le comportement de niveau_batterie sur les huit valeurs suivantes : , , , , , , , .
3. Une fonction imbriquée. On veut maintenant tenir compte du fait que l'appareil est ou non en train de charger. Écrire une fonction message_batterie(pourcentage, en_charge) qui :
- appelle
niveau_batterie(pourcentage)pour obtenir le niveau, - renvoie ce niveau suivi de
" (en charge)"sien_chargevautTrue, - renvoie ce niveau seul sinon.
Vérifier que message_batterie(5, True) renvoie "critique (en charge)".
4. Un piège classique. Un camarade a écrit la version suivante, où les conditions sont rangées dans l'autre sens :
def niveau_batterie_bug(pourcentage):
if pourcentage <= 80:
niveau = "normale"
elif pourcentage <= 30:
niveau = "faible"
elif pourcentage <= 10:
niveau = "critique"
else:
niveau = "pleine"
return niveauQue renvoie niveau_batterie_bug(5) ? Expliquer précisément pourquoi ce réarrangement des conditions produit un résultat incorrect, et énoncer la règle à respecter pour ranger correctement des conditions elif qui se chevauchent.
Choisir entre boucle for et boucle while
1. for ou while ? Pour chacune des quatre situations suivantes, indiquer si une boucle for ou une boucle while est la mieux adaptée, et justifier en une phrase.
a. Parcourir chacune des notes d'une liste pour en calculer la somme. b. Demander un mot de passe à l'utilisateur, encore et encore, jusqu'à ce qu'il soit correct. c. Afficher les 15 premiers multiples de 3. d. Faire croître un capital, année après année, jusqu'à ce qu'il dépasse un seuil fixé.
2. Un rebond de balle. Une balle est lâchée d'une hauteur de 100 cm. À chaque rebond, elle perd la moitié de sa hauteur (on ne conserve que la partie entière, avec la division entière //). On veut savoir combien de rebonds sont nécessaires pour que la hauteur (entière) atteigne 0.
a. Écrire une fonction nombre_de_rebonds(hauteur) qui renvoie ce nombre de rebonds, en utilisant une boucle while. On précisera dans la docstring la précondition sur hauteur et ce que représente la valeur renvoyée.
b. Dérouler à la main l'exécution de nombre_de_rebonds(100), en donnant à chaque tour de boucle la valeur de hauteur et celle du compteur de rebonds.
c. Que renvoie nombre_de_rebonds(0) ? Vérifier que la boucle while de votre fonction se comporte correctement dans ce cas particulier, sans qu'il soit nécessaire d'ajouter un test séparé.
3. Repérer les trois ingrédients d'une boucle while. Le cours rappelle qu'une boucle while correctement construite comporte une initialisation, un test, et une instruction qui modifie une variable du test. Identifier ces trois éléments dans la fonction écrite à la question 2.
Créez un compte gratuit : votre première correction est offerte.
Paramètres, valeur de retour et fonctions imbriquées
On programme le calcul des frais de livraison d'un site de vente en ligne :
def frais_livraison(poids_kg: float, express: bool) -> float:
"""Calcule les frais de livraison a partir du poids (en kg) et du mode
de livraison (express ou standard)."""
base = 2 + 0.5 * poids_kg
if express:
return base + 5
else:
return base1. Paramètres formels et effectifs. Dans la définition de frais_livraison, quels sont les paramètres formels ? Pour l'appel frais_livraison(3, True), quels sont les paramètres effectifs ? Calculer la valeur renvoyée par cet appel, en détaillant le calcul de base.
2. Composer des fonctions. On ajoute une deuxième fonction :
def total_commande(prix_produits: float, poids_kg: float, express: bool) -> float:
"""Calcule le total d'une commande : prix des produits + frais de livraison."""
return prix_produits + frais_livraison(poids_kg, express)Calculer total_commande(50, 3, True), en indiquant précisément à quel moment la fonction frais_livraison est appelée et quelle valeur elle renvoie à total_commande.
3. Une fonction qui ne renvoie rien. On ajoute une troisième fonction :
def afficher_recu(prix_produits, poids_kg, express):
"""Affiche le montant total de la commande."""
total = total_commande(prix_produits, poids_kg, express)
print("Total a payer :", total, "euros")On exécute ensuite :
resultat = afficher_recu(50, 3, True)
print(resultat)Qu'affiche exactement ce code, dans l'ordre ? On justifiera en particulier la valeur affichée par le second print.
4. Portée des variables. La variable base, définie à l'intérieur de frais_livraison, est-elle accessible juste après, dans une instruction print(base) placée en dehors de toute fonction ? Justifier en employant le vocabulaire du cours.
Traduire un algorithme entre Python, pseudo-code et JavaScript
On considère la fonction Python suivante :
def somme_pairs(tableau):
"""Renvoie la somme des elements pairs du tableau."""
somme = 0
for element in tableau:
if element % 2 == 0:
somme = somme + element
return somme1. Dérouler l'exécution. Dérouler somme_pairs([1, 2, 3, 4, 5, 6]) en donnant, pour chaque valeur de element, si elle est retenue ou non et la valeur de somme après son passage dans la boucle.
2. Vers le pseudo-code. Traduire somme_pairs en pseudo-code, en reprenant exactement la syntaxe utilisée en cours (mots-clés Fonction... FinFonction, Pour... FinPour, Si... Alors... FinSi, affectation notée <-).
3. Vers JavaScript. Traduire somme_pairs en JavaScript, en respectant les conventions de syntaxe vues en cours pour ce langage (déclaration de variable avec var, bloc délimité par des accolades, boucle for indicée, console.log pour afficher).
4. Trois différences. En comparant les trois versions, citer trois différences purement syntaxiques entre Python et JavaScript (parmi celles données par le tableau du cours ou observées ici), en précisant à chaque fois qu'elles ne changent rien à ce que le programme calcule.
Créez un compte gratuit : votre première correction est offerte.
Écrire le contrat d'une fonction : préconditions et postconditions
On veut écrire une fonction premier_diviseur(n) qui, étant donné un entier n supérieur ou égal à 2, renvoie le plus petit diviseur de n supérieur ou égal à 2 (ce diviseur existe toujours, puisque n se divise lui-même).
1. Spécifier avant de coder. Écrire, sous forme de docstring, le contrat de cette fonction (précondition et postcondition), avant même d'en écrire le code, en suivant exactement la présentation du cours.
2. Raisonner sur le contrat seul. Sans écrire une seule ligne de code, et en utilisant uniquement l'énoncé du contrat, donner la valeur que doit renvoyer premier_diviseur(21), puis celle que doit renvoyer premier_diviseur(29) (on rappelle que 29 est un nombre premier).
3. Implémenter et vérifier la précondition. Écrire le code de premier_diviseur, en utilisant une boucle while, et en faisant vérifier la précondition par une instruction assert munie d'un message d'erreur explicite.
4. Que se passe-t-il si la précondition n'est pas respectée ? On considère la fonction de la question 3, mais sans l'instruction assert de vérification de précondition.
- Décrire précisément ce qui se produit lors de l'appel
premier_diviseur(1). - Décrire précisément ce qui se produit lors de l'appel
premier_diviseur(0). - Lequel des deux comportements est le plus dangereux, et pourquoi ?
Créez un compte gratuit : votre première correction est offerte.
Concevoir un jeu de tests et utiliser une bibliothèque standard
Un camarade a écrit la fonction suivante, censée déterminer si une chaîne de caractères est un palindrome (elle se lit de la même façon à l'endroit et à l'envers) :
def est_palindrome_v2(mot):
"""Renvoie True si mot se lit de la meme facon a l'endroit et a l'envers."""
n = len(mot)
for i in range(n // 2 - 1):
if mot[i] != mot[n - i - 1]:
return False
return True1. Dérouler l'exécution. Dérouler est_palindrome_v2("abca") : donner la valeur de n, l'ensemble des valeurs prises par i, et la valeur finalement renvoyée.
2. Le mot "abca" est-il un palindrome ? Vérifier à la main, en comparant "abca" à son écriture à l'envers, si c'est bien un palindrome. Que peut-on en conclure sur la fonction est_palindrome_v2 ?
3. Localiser et corriger le bug. Expliquer précisément l'erreur commise dans la borne de range(...), puis proposer une version corrigée est_palindrome(mot).
4. Un jeu de tests représentatif. Écrire un jeu de tests (assert) pour la fonction corrigée, incluant au moins : la chaîne vide, un mot d'une seule lettre, un palindrome de longueur paire, un non-palindrome de longueur paire (on pourra réutiliser "abca"), un palindrome de longueur impaire, et un non-palindrome de longueur impaire.
5. Bibliothèques.
a. Quelle instruction, tapée dans l'interpréteur Python, permet d'afficher la documentation de la fonction est_palindrome sans quitter Python ni consulter internet ?
b. Le module math fournit la fonction math.floor, qui renvoie la partie entière par défaut d'un nombre. Montrer que, pour un entier n positif ou nul, math.floor(n / 2) et n // 2 renvoient toujours le même résultat.
c. La fonction est_palindrome est-elle une fonction qui utilise le hasard, comme la fonction lancer_de vue en cours ? Pourquoi le jeu de tests de la question 4, qui compare directement à des valeurs exactes, est-il suffisant ici, alors qu'il ne le serait pas pour tester lancer_de ?
Créez un compte gratuit : votre première correction est offerte.
Sujet type bac : gérer les réservations d'une salle de cinéma
Une salle de cinéma comporte un nombre total de places fixé à l'avance. On souhaite programmer la gestion des réservations.
Partie A — Places disponibles.
Écrire une fonction places_disponibles(total, reservees) qui renvoie le nombre de places encore libres. On précisera dans la docstring la précondition (reservees ne peut ni être négatif, ni dépasser total) et on la fera vérifier par une instruction assert.
Partie B — Une demande peut-elle être satisfaite ?
Écrire une fonction peut_reserver(total, reservees, demande) qui renvoie True si demande places supplémentaires peuvent encore être réservées, False sinon. Cette fonction devra appeler places_disponibles.
Partie C — Traiter une liste de demandes.
On reçoit, dans l'ordre, une liste de demandes de réservation (chaque demande est un entier, le nombre de places souhaitées). On veut traiter ces demandes une par une : si une demande peut être satisfaite compte tenu des places déjà réservées, on l'accepte et on met à jour le nombre de places réservées ; sinon, on la refuse et on passe à la suivante.
- Écrire une fonction
traiter_demandes(total, demandes)qui renvoie un couple(reservees, honorees), oùreserveesest le nombre total de places finalement réservées ethonoreesle nombre de demandes qui ont pu être satisfaites. - Dérouler
traiter_demandes(10, [3, 4, 5, 2])demande par demande, en indiquant à chaque étape le nombre de places disponibles, si la demande est acceptée ou refusée, et les valeurs dereserveesethonoreesaprès traitement de la demande. - Écrire un jeu de tests (
assert) pourtraiter_demandes, incluant au moins : une liste de demandes vide, et une demande dont la taille est exactement égale au nombre de places disponibles au moment où elle est traitée.
Partie D — Cohérence des préconditions.
Expliquer pourquoi l'appel à places_disponibles(total, reservees) réalisé à l'intérieur de peut_reserver, puis à l'intérieur de traiter_demandes, ne déclenche jamais l'erreur de l'assert écrit en partie A, quelle que soit la liste demandes fournie.
Créez un compte gratuit : votre première correction est offerte.