Le cours complet Variables, types et affectation
Définition · Variable et affectation
Une variable associe un nom à une valeur stockée en mémoire. L'affectation donne (ou change) cette valeur :
Attention · Le = n'est pas l'égalité des maths
En maths, « \(x=x+1\) » est faux (aucun nombre n'égale son successeur). En programmation, x = x + 1 est un ordre parfaitement valide : « calcule x+1 et range le résultat dans x ». Pour tester une égalité (et obtenir vrai/faux), on utilise un double égal : x == 1. Si la lecture hésite, remplace mentalement = par « reçoit » et == par « est-il égal à ? ». Ces deux verbes n'accomplissent pas la même action.
Exemple · Échanger deux variables
Pour échanger les contenus de a et b, on passe par une variable temporaire (sinon on écrase une valeur) :
a = 3
b = 8
temp = a # on met de cote l'ancien a
a = b # a recoit b
b = temp # b recoit l'ancien a
print(a, b) # affiche 8 3
À toi d’essayer
Pourquoi l'ordre des lignes compte Prédis les valeurs finales après a = 3, puis b = 8, puis a = b, puis b = a. Ce code échange-t-il les deux valeurs ? Répare-le sans utiliser l'affectation simultanée de Python.
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Après a = b, l'ancienne valeur \(3\) n'est plus dans a.
Indice 2 · Un pas de plus Conserve cette ancienne valeur dans une troisième variable avant de remplacer a.
Voir l’explication La trace donne successivement \((a,b)=(3,8)\) , puis \((8,8)\) , puis \((8,8)\) : l'échange n'a pas eu lieu. La réparation est temp = a, puis a = b, puis b = temp, ce qui donne \((8,3)\) . À chaque affectation, on évalue d'abord la droite avec les valeurs courantes, puis on remplace la valeur de gauche. Réessaie : trace x = 2, y = x + 3, x = y * 2 ; la valeur de y change-t-elle lors de la dernière ligne ?
Exemple · Lire les opérations avant de les utiliser
Code Résultat Question résolue 7 / 23.5division 7 // 23quotient entier 7 % 21reste 2 ** 38puissance \(\texttt{7 == 2}\) Falsecomparaison
Avec un diviseur positif, // arrondit vers le bas, même pour un résultat négatif : -7 // 2 vaut \(-4\) et -7 % 2 vaut \(1\) , puisque \(-7=2\times(-4)+1\) . Une division par zéro n'est pas définie. Le point de 3.5 est la notation décimale de Python ; la virgule sert à séparer des objets.
Attention · Un flottant est une approximation
En Python, 0.1 + 0.2 == 0.3 donne False : ces décimaux n'ont pas tous une représentation binaire finie. Ce n'est pas un contre-exemple à l'égalité mathématique. Pour une comparaison approchée, on choisit une tolérance justifiée par le problème, par exemple abs(x - y) < 1e-9. Cette tolérance ne rend pas exact un calcul approché.
Instructions conditionnelles : choisir
Définition · Conditionnelle if / elif / else
Une instruction conditionnelle exécute un bloc si une condition est vraie, un autre sinon . En Python, l'indentation (le décalage) délimite les blocs.
if note >= 10:
print("Admis")
elif note >= 8:
print("Rattrapage")
else:
print("Refuse")
Intuition · Suivre les deux tests dans l'ordre
Le premier test vrai sélectionne une branche ; les suivantes sont ignorées. L'organigramme reprend exactement le programme précédent. Agrandir ↗ Les étiquettes sont celles d'un exemple de classement ; ce programme n'est pas une règle réglementaire d'examen.
À toi d’essayer
Un test vrai peut empêcher de lire le suivant Pour les valeurs \(7\) , \(8\) , \(9\) et \(10\) , prédis la sortie du programme précédent. Que se passe-t-il si on place le test note >= 8 avant celui de note >= 10, dans la même chaîne if / elif ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Teste les bornes exactes : \(8\geqslant8\) et \(10\geqslant10\) sont vrais.
Indice 2 · Un pas de plus Dans une chaîne if / elif, un premier test vrai suffit à choisir la branche.
Voir l’explication Dans l'ordre initial, on obtient Refusé, Rattrapage, Rattrapage, Admis. En inversant l'ordre des deux tests avec leurs actions, une note de \(10\) satisfait déjà note >= 8 et reçoit Rattrapage ; le second test n'est plus évalué. Deux if séparés pourraient, eux, exécuter deux blocs. Réessaie : trace les deux variantes pour \(12\) , puis explique pourquoi l'ordre initial traite d'abord le groupe le plus restrictif.
Boucles bornées : répéter un nombre connu de fois
Définition · Boucle for
La boucle for répète un bloc pour chaque valeur d'une plage. range(a, b) parcourt les entiers de a à b-1 (la borne de droite est exclue ).
somme = 0
for k in range(1, 101): # k va de 1 a 100
somme = somme + k
print(somme) # 5050
Attention · range(a, b) s'arrête à b-1
range(1, 5) produit 1, 2, 3, 4 : quatre valeurs, pas cinq. Pour parcourir \(1\) à \(n\) inclus , on écrit range(1, n+1). Oublier le +1 est une erreur très fréquente. range(n) seul donne 0, 1, …, n-1 (\(n\) valeurs en partant de \(0\) ).
À toi d’essayer
Voir une somme se construire On initialise s = 0, puis, pour k in range(1, 5), on exécute s = s + k*k. Prédis la valeur finale et construis une ligne de trace par tour. Que se passe-t-il avec range(1, 1) ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Les valeurs de k sont \(1,2,3,4\) ; \(5\) est exclu.
Indice 2 · Un pas de plus La nouvelle somme est l'ancienne somme plus le carré courant, pas seulement le carré courant.
Voir l’explication La trace est :
\(k\) ancien \(s\) \(k^2\) nouveau \(s\) 1 0 1 1 2 1 4 5 3 5 9 14 4 14 16 30
La valeur finale est \(30\) . Avec range(1, 1), aucun tour n'a lieu et s reste \(0\) . Initialiser l'accumulateur avant la boucle permet de garder les apports précédents. Réessaie : calcule la somme des cubes de \(1\) à \(3\) en adaptant exactement deux endroits.
Boucles non bornées : répéter jusqu'à une condition
Définition · Boucle while
La boucle while répète un bloc tant que sa condition reste vraie. On l'utilise quand on ne sait pas d'avance combien de répétitions seront nécessaires (recherche de seuil, par exemple).
capital = 1000
annees = 0
while capital < 2000: # tant qu'on n'a pas double
capital = capital * 1.05 # +5% par an
annees = annees + 1
print(annees) # nombre d'annees pour doubler
Attention · Augmenter ne suffit pas à garantir l'arrêt
Il faut justifier que le seuil sera atteint, pas seulement que la variable change. Par exemple, \(u_{n+1}=(u_n+2)/2\) avec \(u_0=0\) augmente mais reste strictement sous \(2\) : une boucle « tant que \(u<2\) » ne s'arrête pas en arithmétique exacte. Des flottants peuvent finir par arrondir à \(2\) ; cet arrêt numérique ne prouve pas que la suite atteint \(2\) . Pour le capital multiplié par \(1{,}05\) , la croissance géométrique dépasse tout seuil fixé positif, ce qui justifie l'arrêt dans le modèle mathématique.
Intuition · Organigramme du while
On teste avant chaque tour : si la condition est vraie, on exécute le bloc puis on revient au test ; sinon on sort.
Agrandir ↗
À toi d’essayer
Lire le test avant chaque tour On initialise u = 1, n = 0. Tant que u <= 8, on double u, puis on augmente n de \(1\) . Quelle valeur finale de n obtient-on ? Pourquoi le résultat change-t-il avec u < 8 ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Le test est fait avant le tour, y compris lorsque u vaut exactement \(8\) .
Indice 2 · Un pas de plus Trace les couples \((n,u)\) depuis \((0,1)\) jusqu'au premier test faux.
Voir l’explication Les couples sont \((0,1),(1,2),(2,4),(3,8),(4,16)\) . Avec <=, le programme s'arrête à \(n=4\) , premier rang où \(u>8\) . Avec <, il s'arrête à \(n=3\) , premier rang où \(u\geqslant8\) . Le choix du test vient du seuil strict ou large demandé. Réessaie : remplace le seuil par \(0\) ; combien de tours sont effectués ?
Fonctions et programmation modulaire
Définition · Fonction
Une fonction regroupe un bloc d'instructions sous un nom . Elle reçoit des paramètres (entrées) et renvoie un résultat avec return.
def aire_disque(rayon):
return 3.14159 * rayon**2
a = aire_disque(2) # appel : rayon vaut 2
print(a) # 12.56636
Attention · return n'est pas print
print affiche une valeur à l'écran (pour l'humain) mais ne la renvoie pas au programme. return renvoie la valeur pour qu'on puisse la réutiliser (la stocker, la recombiner). Pour réutiliser un résultat calculé, une fonction doit le renvoyer avec return, pas seulement l'afficher : sinon sa valeur de retour est None, que l'on ne peut pas additionner comme le résultat numérique attendu. Après un return, la fonction s'arrête immédiatement.
Méthode · Programmation modulaire : découper en sous-tâches
Pour un problème complexe :
Identifier les sous-tâches indépendantes (« calculer la moyenne », « chercher le maximum »…).
Écrire une fonction pour chacune, avec un nom clair et un return.
Tester chaque fonction séparément sur des cas simples.
Assembler les fonctions dans un programme principal.
On obtient un code lisible, testable et réutilisable.
Exemple · Un appel, une valeur renvoyée
def carre(x):
resultat = x*x
return resultat
y = carre(3) + carre(4)
Le premier appel calcule \(9\) , le second \(16\) . Le programme additionne ces valeurs puis affecte \(25\) à y. Les noms x et resultat sont locaux à chaque appel ; ils ne sont pas automatiquement disponibles après la fonction. La définition seule ne lance aucun calcul : il faut un appel.
À toi d’essayer
Un affichage peut cacher une absence de résultat On remplace return resultat par print(resultat) dans la fonction précédente. Que voit-on, et l'affectation à y réussit-elle ? Comment conserver à la fois un résultat réutilisable et un affichage ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Afficher une valeur et la transmettre comme résultat d'un appel sont deux opérations différentes.
Indice 2 · Un pas de plus Sans return explicite, l'appel renvoie None.
Voir l’explication Le programme affiche \(9\) puis \(16\) , mais essaie ensuite d'additionner None et None : l'affectation à y échoue. Il faut conserver return resultat dans la fonction, puis écrire print(y) après l'affectation. Réessaie : écris une fonction qui renvoie \(2x+1\) et utilise son résultat dans une multiplication.
Les listes : la grande nouveauté
Définition · Liste
Une liste range plusieurs valeurs dans un ordre précis, sous un seul nom. Chaque élément a un indice (sa position), qui commence à 0 .
L = [5, 12, 8, 20] # liste en extension
print(L[0]) # 5 (premier element, indice 0)
print(L[3]) # 20 (quatrieme element, indice 3)
print(len(L)) # 4 (nombre d'elements)
Attention · Les indices commencent à 0
Dans une liste de longueur \(n\) , les indices valides vont de 0 à n-1. Le premier élément est L[0], le dernier est L[n-1] (ou L[-1] en Python). Accéder à L[n] provoque une erreur (indice hors limites). Si un indice est hors limites, compare-le à la longueur et vérifie si tu as confondu position et nombre d'éléments.
Propriété · Trois façons de créer une liste
# 1. En extension : on ecrit les elements
carres = [0, 1, 4, 9, 16]
# 2. Par ajouts successifs : on part du vide et on remplit
carres = []
for k in range(5):
carres.append(k**2) # ajoute k^2 a la fin
# 3. En comprehension : une formule + une plage (+ une condition)
carres = [k**2 for k in range(5)]
pairs = [k for k in range(20) if k % 2 == 0] # avec condition
Intuition · Une liste conserve l'ordre et les répétitions
[k**2 for k in range(-2, 3)] donne [4, 1, 0, 1, 4]. La compréhension évalue une expression pour chaque élément parcouru, dans cet ordre. Un ensemble mathématique des carrés correspondants serait \(\{0,1,4\}\) : il n'enregistre ni ordre ni doublons. Le filtre if conserve certains éléments, sans supprimer automatiquement les répétitions.
À toi d’essayer
Indice, valeur et filtre Avec L = [4, 1, 0, 1, 4], donne L[1], len(L), L[-1] et le résultat de [x for x in L if x > 0]. Le dernier résultat contient-il deux fois \(4\) ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste L'indice \(1\) désigne le deuxième élément, pas l'élément de valeur \(1\) recherché.
Indice 2 · Un pas de plus Le filtre examine chacune des cinq positions ; il retire seulement les valeurs qui ne satisfont pas le test.
Voir l’explication On obtient \(1\) , \(5\) , \(4\) , puis [4, 1, 1, 4]. Le zéro a été exclu ; les deux \(4\) sont conservés. Pour une liste vide, aucun indice n'est valide, même -1. Réessaie : construis la liste des \(k^2\) pour \(k\) allant de \(-3\) à \(3\) inclus, puis garde uniquement les carrés strictement supérieurs à \(1\) .
Propriété · Deux façons de parcourir une liste
L = [5, 12, 8, 20]
# Parcourir par INDICES (utile si on a besoin de la position)
for i in range(len(L)):
print(i, L[i])
# ITERER sur les ELEMENTS (plus simple si la position est inutile)
for valeur in L:
print(valeur)
Exemple · Moyenne d'une liste de notes
def moyenne(notes):
if len(notes) == 0:
return None # liste vide : pas de moyenne
return sum(notes) / len(notes)
print(moyenne([12, 8, 15, 10])) # 11.25
À toi d’essayer
Compter ou additionner : deux accumulateurs différents Pour L = [-2, 5, 0, 5], calcule le nombre d'éléments strictement positifs et leur somme. Propose une boucle qui met à jour deux variables nombre et total. Que doivent-elles valoir pour une liste vide ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Le nombre augmente de \(1\) ; la somme augmente de la valeur lue.
Indice 2 · Un pas de plus Le zéro ne vérifie pas le test strict x > 0. Initialise les deux variables avant la boucle.
Voir l’explication On obtient \(2\) éléments et une somme de \(10\) . Initialise nombre = 0 et total = 0, parcours les éléments, puis, si x > 0, ajoute \(1\) à nombre et x à total. Pour une liste vide, aucun tour n'est exécuté et les deux résultats valent \(0\) . Une moyenne des éléments positifs n'est définie que si leur nombre est non nul. Réessaie : applique ce raisonnement à [-3, 0, -1] avant toute division.
Attention · Complément : deux noms peuvent désigner la même liste
Après A = [1, 2] puis B = A, ajouter \(3\) avec B.append(3) modifie aussi la liste visible par A : les deux noms désignent le même objet. Pour copier une liste de nombres et la modifier séparément, on peut écrire B = A.copy(). Cette copie suffit ici ; des listes contenant d'autres listes demanderaient de préciser davantage ce que l'on copie.
Un peu de logique et d'ensembles
Définition · Ensembles : appartenance, inclusion, opérations
Un ensemble est une collection d'éléments. On note :
\(x\in A\) : « \(x\) appartient à \(A\) » ; \(A\subset B\) : « \(A\) est inclus dans \(B\) » (tout élément de \(A\) est dans \(B\) ) ;
\(A\cap B\) : l'intersection (éléments dans \(A\) et dans \(B\) ) ; \(A\cup B\) : la réunion (dans \(A\) ou dans \(B\) ) ;
\(\overline A\) (ou \(E\setminus A\) ) : le complémentaire de \(A\) dans \(E\) (les éléments de \(E\) qui ne sont pas dans \(A\) ).
Agrandir ↗
Définition · Logique : connecteurs, implication, équivalence
« \(P\) et \(Q\) » est vraie quand les deux le sont ; « \(P\) ou \(Q\) » est vraie quand au moins une l'est.
Implication \(P\Rightarrow Q\) : « si \(P\) alors \(Q\) ». \(P\) est une condition suffisante pour \(Q\) ; \(Q\) est une condition nécessaire pour \(P\) .
Réciproque de \(P\Rightarrow Q\) : c'est \(Q\Rightarrow P\) (attention, elle peut être fausse même si l'implication est vraie).
Équivalence \(P\Leftrightarrow Q\) : \(P\Rightarrow Q\) et \(Q\Rightarrow P\) (« \(P\) si et seulement si \(Q\) »).
Attention · Une implication n'est pas sa réciproque
« S'il pleut, alors le sol est mouillé » est vraie. Sa réciproque « si le sol est mouillé, alors il pleut » est fausse (quelqu'un a pu arroser). De même en maths : « \(x=2\Rightarrow x^2=4\) » est vraie, mais la réciproque « \(x^2=4\Rightarrow x=2\) » est fausse (car \(x=-2\) marche aussi). Un seul contre-exemple suffit à montrer qu'une proposition est fausse.
À toi d’essayer
Nier une condition sans perdre les bornes Pour un réel \(x\) , nie « \(x>0\) et \(x<2\) ». Écris un test Python correspondant à cette négation. Puis nie « tous les éléments de la liste sont strictement positifs » et explique ce qui se passe pour une liste vide.
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste La négation de « et » utilise « ou ». La négation de \(x>0\) inclut \(0\) .
Indice 2 · Un pas de plus Une valeur strictement positive ne réfute pas « tous strictement positifs » ; il faut une valeur qui ne soit pas strictement positive.
Voir l’explication La première négation est \(x\leqslant0\) ou \(x\geqslant2\) , soit x <= 0 or x >= 2. La seconde est « il existe au moins un élément inférieur ou égal à \(0\) ». Une liste vide n'a aucun contre-exemple : « tous ses éléments sont strictement positifs » est vraie au sens logique, tandis que « elle contient un élément strictement positif » est fausse. Réessaie : nie « il existe un élément supérieur à \(10\) » et écris un test qui cherche un contre-exemple à ta négation.
Couples et produit cartésien
Définition · Couple
Un couple \((x,y)\) est un objet ordonné : en général, \((x,y)\neq(y,x)\) . L'ordre compte, comme pour les coordonnées d'un point. Si \(A\) et \(B\) sont deux ensembles, leur produit cartésien est
\[\boxed{A\times B=\{(x,y)\mid x\in A\ \text{et}\ y\in B\}.}\]
Exemple · Construire un produit cartésien
Si \(A=\{1,2\}\) et \(B=\{a,b,c\}\) , alors
\[\begin{aligned}&A\times B\\[.35em]&= \{(1,a),(1,b),(1,c),(2,a),(2,b),(2,c)\}.\end{aligned}\]
Il contient \(2\times3=6\) couples. En Python :
A = [1, 2]
B = ["a", "b", "c"]
produit = [(x, y) for x in A for y in B]
Les deux boucles correspondent aux deux choix successifs : un élément de \(A\) , puis un élément de \(B\) .
À toi d’essayer
Deux boucles, quel ordre de résultats ? Avec A = [1, 2] et B = ["a", "b", "c"], prédis l'ordre des couples de [(x, y) for x in A for y in B]. Que donne la même expression si B est vide ?
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste La boucle sur \(x\) est extérieure : pour une valeur fixée de \(x\) , la boucle sur \(y\) est parcourue entièrement.
Indice 2 · Un pas de plus Chaque élément de \(A\) est associé successivement aux trois éléments de \(B\) .
Voir l’explication L'ordre est \((1,a),(1,b),(1,c),(2,a),(2,b),(2,c)\) . Il y a \(2\times3=6\) couples. Si \(B\) est vide, aucun couple n'est créé et le résultat est une liste vide. Les listes doivent être sans doublons si l'on veut que chaque couple du produit cartésien apparaisse exactement une fois. Réessaie : inverse l'ordre des boucles en conservant l'expression (x, y) et prédis le nouvel ordre.
Identité, équation et statut des lettres
Définition · Ne pas confondre les statuts
Une identité est vraie pour toutes les valeurs autorisées : \((x+1)^2=x^2+2x+1\) .
Une équation n'est vraie que pour certaines valeurs : \((x+1)^2=9\) .
Une variable peut prendre plusieurs valeurs ; une inconnue est une valeur à trouver ; un paramètre est fixé pendant le calcul mais peut ensuite varier d'une situation à l'autre.
La même lettre peut changer de statut selon la phrase : c'est l'énoncé qui fixe son rôle.
Exemple · Lire avant de calculer
Dans \(x^2-2mx+1=0\) , on résout en général par rapport à l'inconnue \(x\) , tandis que \(m\) est un paramètre . Dans une fonction Python def f(x):, la lettre x est un paramètre de la fonction : sa valeur sera fournie lors de l'appel.
Trois structures de raisonnement
Une preuve à construire
Couvrir tous les entiers par deux cas Pour tout entier \(n\) , démontre que \(n(n+1)\) est pair en distinguant deux cas.
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Un entier est pair ou impair ; ces deux cas couvrent tous les entiers.
Indice 2 · Un pas de plus Dans chaque cas, identifie un facteur de la forme \(2k\) .
Voir la preuve expliquée Si \(n=2k\) avec \(k\) entier, alors \(n(n+1)=2k(n+1)\) est pair. Si \(n=2k+1\) , alors \(n+1=2(k+1)\) , donc \(n(n+1)=2n(k+1)\) est pair. Les facteurs restants sont entiers et les deux cas couvrent toutes les possibilités. Quelques essais numériques suggèrent la propriété ; les deux cas expliquent pourquoi aucun entier n'y échappe.
Une preuve à construire
Une implication à prouver en changeant de sens Pour un entier \(n\) , prouve : si \(n^2\) est pair, alors \(n\) est pair. Formule d'abord sa contraposée, en la distinguant de sa réciproque.
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste La contraposée de « \(P\) implique \(Q\) » est « non \(Q\) implique non \(P\) ».
Indice 2 · Un pas de plus Écris un entier impair sous la forme \(2k+1\) , puis calcule son carré.
Voir la preuve expliquée La contraposée est : « si \(n\) est impair, alors \(n^2\) est impair ». Pour \(n=2k+1\) ,
\[\begin{aligned}n^2&=(2k+1)^2\\[.35em]&=4k^2+4k+1\\[.35em]&=2(2k^2+2k)+1.\end{aligned}\]
Le nombre entre parenthèses est entier : le carré est impair. La contraposée, logiquement équivalente à l'implication initiale, est démontrée. La réciproque serait « si \(n\) est pair, alors \(n^2\) est pair » : elle est aussi vraie ici, mais n'est pas l'énoncé que nous venons d'utiliser.
Une preuve à construire
Faire apparaître une contradiction Démontre qu'aucun entier n'est à la fois pair et impair. Écris explicitement ce que suppose un raisonnement par l'absurde.
Tu peux chercher, prendre un indice ou lire l’explication, à ton rythme.
Indice 1 · Une piste Suppose qu'il existe un entier possédant les deux propriétés.
Indice 2 · Un pas de plus Il s'écrirait à la fois \(2p\) et \(2q+1\) , avec \(p,q\) entiers.
Voir la preuve expliquée Supposons qu'un tel entier \(n\) existe. Alors \(2p=2q+1\) , donc \(p-q=1/2\) . Or la différence de deux entiers est entière, tandis que \(1/2\) ne l'est pas. Cette contradiction interdit l'existence supposée ; aucun entier n'a donc les deux propriétés. La contradiction doit venir des hypothèses et de propriétés connues, pas seulement d'un résultat inattendu.
Attention · Une preuve doit couvrir tous les cas
Tester quelques valeurs avec Python peut suggérer une propriété, mais une boucle finie ne prouve jamais une affirmation portant sur une infinité d'entiers. Le programme aide à conjecturer ; le raisonnement explique pourquoi c'est vrai pour tous les cas.
Exercices Exercice 1 ★☆☆ : Lire une affectation
On exécute : a = 4 ; b = 7 ; a = a + b ; b = a - b. Quelles sont les valeurs finales de a et b ?
Exercice 2 ★☆☆ : Trace d'une boucle
Que vaut s après ce code ? Détailler les valeurs successives.
s = 0
for k in range(1, 5):
s = s + k
Exercice 3 ★☆☆ : Lire une liste
Soit L = [3, 9, 1, 7, 4]. Donner L[0], L[2], len(L), L[len(L)-1], et la valeur de sum(L).
Exercice 4 ★☆☆ : Pair ou impair
Écrire une fonction parite(n) qui renvoie la chaîne "pair" si n est pair, "impair" sinon. (Indice : n % 2 vaut \(0\) si n est pair.)
Exercice 5 ★☆☆ : Compter
Écrire une fonction compte_pairs(L) qui renvoie le nombre d'éléments pairs d'une liste L.
Exercice 6 ★☆☆ : Liste en compréhension
Écrire, en une seule ligne (compréhension), la liste des cubes \(k^3\) pour \(k\) de \(1\) à \(10\) . Puis la liste des multiples de \(3\) entre \(0\) et \(30\) inclus.
Exercice 7 ★★☆ : Somme conditionnelle
Écrire une fonction somme_positifs(L) qui renvoie la somme des éléments strictement positifs d'une liste L.
Exercice 8 ★★☆ : Table de multiplication
Écrire une fonction table(n) qui renvoie la liste [n, 2n, 3n, ..., 10n].
Exercice 9 ★★☆ : Maximum et sa position
Pour une liste non vide de nombres, écrire une fonction indice_max(L) qui renvoie l'indice du plus grand élément (le premier en cas d'égalité).
Exercice 10 ★★☆ : Suite et seuil
On définit \(u_0=2\) et \(u_{n+1}=1{,}5\,u_n\) . Écrire une fonction seuil(S) qui renvoie le plus petit \(n\) tel que \(u_n>S\) .
Exercice 11 ★★☆ : Recherche dans une liste
Écrire une fonction est_present(x, L) qui renvoie True si x apparaît dans L, False sinon, sans le test d'appartenance x in L. Une boucle de parcours for ... in L est autorisée.
Exercice 12 ★★★ : Logique et méthodes de preuve
1. Pour chaque implication, dire si elle est vraie, puis donner sa réciproque et dire si elle est vraie.
2. Nier correctement : « tous les élèves ont réussi » ; « il existe un entier pair supérieur à \(100\) » ; « \(x>0\) et \(x<2\) ».
3. Démontrer par disjonction des cas que \(n(n+1)\) est pair pour tout entier \(n\) .
4. Démontrer par contraposée : si \(n^2\) est pair, alors \(n\) est pair.
5. Démontrer par l'absurde qu'aucun entier ne peut être à la fois pair et impair.
Exercice 13 ★★★ : Tester et lister les nombres premiers
Écrire une fonction est_premier(n) qui renvoie True si n est premier (\(n\geqslant 2\) ), puis une fonction premiers_jusqua(N) qui renvoie la liste des nombres premiers inférieurs ou égaux à N.
Exercice 14 ★★★ : Simulation et espérance
On lance indépendamment deux dés équilibrés et on s'intéresse à la somme \(S\) . Écrire une fonction moyenne_somme(n) qui simule n lancers de deux dés et renvoie la moyenne des sommes obtenues, pour un entier \(n>0\) . Autour de quelle valeur les moyennes de grands échantillons se concentrent-elles dans ce modèle ? (Lien fiche 10.)
Exercice 15 ★★★ : Inverser une liste
Écrire une fonction renverse(L) qui renvoie une nouvelle liste contenant les éléments de L dans l'ordre inverse, sans utiliser L.reverse() ni L[::-1].
Exercice 16 ★★★ : Ensembles et produit cartésien via les listes
1. Écrire une fonction intersection(A, B) qui renvoie la liste des éléments présents à la fois dans A et dans B (sans doublon). Relier au symbole mathématique correspondant.
2. Écrire une fonction produit_cartesien(A, B) qui renvoie la liste de tous les couples \((x,y)\) avec \(x\in A\) et \(y\in B\) . Combien de couples obtient-on si \(A\) contient \(p\) éléments et \(B\) en contient \(q\) ?
Corrigés détaillés Corrigé 1
Démonstration
On suit les affectations ligne par ligne , en gardant en tête les valeurs des boîtes :
a = 4 : \(a=4\) . b = 7 : \(b=7\) .
a = a + b :
\[\begin{aligned}a &= 4+7\\[.35em]&= 11\end{aligned}\]
(et \(b\) reste \(7\) ).
b = a - b :
\[\begin{aligned}b &= 11-7\\[.35em]&= 4.\end{aligned}\]
Valeurs finales : \(\boxed{a=11,\ b=4}\) . (Ce code échange presque les valeurs, mais a garde la somme.)
Corrigé 2
Démonstration
range(1, 5) parcourt \(k=1,2,3,4\) . On accumule dans s :
\[s:\ 0\xrightarrow{+1}1\xrightarrow{+2}3\xrightarrow{+3}6\xrightarrow{+4}10.\]
Donc s vaut \(\boxed{10}\) .
Corrigé 3
Démonstration
L = [3, 9, 1, 7, 4]. Les indices vont de \(0\) à \(4\) :
\[\begin{aligned}\texttt{L[0]} &=3,\\[.35em]\texttt{L[2]} &=1,\\[.35em]\texttt{len(L)} &=5,\\[.35em]\texttt{L[len(L)-1]} &= \texttt{L[4]}\\[.35em]&= 4.\end{aligned}\]
\[\begin{aligned}\texttt{sum(L)} &= 3+9+1+7+4\\[.35em]&= 24.\end{aligned}\]
Corrigé 4
Démonstration
def parite(n):
if n % 2 == 0:
return "pair"
else:
return "impair"
Le test n % 2 == 0 vérifie que le reste de la division par \(2\) est nul. Noter le double égal == (test) et le : suivi de l'indentation.
Corrigé 5
Démonstration
On parcourt la liste et on compte :
def compte_pairs(L):
c = 0
for x in L:
if x % 2 == 0:
c = c + 1
return c
On itère directement sur les éléments (for x in L) car la position ne sert pas. c compte les nombres pairs rencontrés.
Corrigé 6
Démonstration
cubes = [k**3 for k in range(1, 11)] # 1 a 10 inclus
mult3 = [k for k in range(0, 31) if k % 3 == 0]
Pour aller jusqu'à \(10\) inclus , on écrit range(1, 11). La condition if k%3==0 ne garde que les multiples de \(3\) . Résultats : [1, 8, 27, ..., 1000] et [0, 3, 6, ..., 30].
Corrigé 7
Démonstration
def somme_positifs(L):
s = 0
for x in L:
if x > 0:
s = s + x
return s
On n'ajoute x à la somme que s'il est strictement positif. Par exemple sur [3, -2, 5, -7] on obtient \(3+5=8\) .
Corrigé 8
Démonstration
def table(n):
return [n * k for k in range(1, 11)]
La compréhension construit [n*1, n*2, ..., n*10]. On pouvait aussi partir d'une liste vide et faire append dans une boucle : les deux méthodes sont équivalentes.
Corrigé 9
Démonstration
On retient à la fois la valeur du maximum et son indice :
def indice_max(L):
imax = 0
for i in range(len(L)):
if L[i] > L[imax]:
imax = i
return imax
On compare chaque élément L[i] au meilleur trouvé L[imax]. L'inégalité stricte > garantit qu'en cas d'égalité on garde le premier indice. Ici on parcourt par indices car c'est la position qu'on veut renvoyer.
Corrigé 10
Démonstration
def seuil(S):
u = 2 # u_0
n = 0
while u <= S:
u = 1.5 * u # u_{n+1} = 1.5 u_n
n = n + 1
return n
La suite est géométrique de raison \(1{,}5>1\) , donc elle croît sans limite : le while finit toujours par s'arrêter. On compte dans n le nombre d'étapes jusqu'à dépasser S. Par exemple seuil(10) renvoie \(4\) (car \(u_0=2,\,u_1=3,\,u_2=4{,}5,\,u_3=6{,}75,\,u_4=10{,}125>10\) ).
Corrigé 11
Démonstration
def est_present(x, L):
for valeur in L:
if valeur == x:
return True # trouve : on sort tout de suite
return False # parcours fini sans trouver
Dès qu'on trouve x, le return True arrête la fonction (inutile de continuer). Si la boucle se termine sans rien trouver, on renvoie False.
Corrigé 12
Démonstration
1(a). « \(n\) multiple de \(4\Rightarrow n\) pair » : vraie (tout multiple de \(4\) est multiple de \(2\) ). Réciproque : « \(n\) pair \(\Rightarrow n\) multiple de \(4\) » : fausse (\(n=2\) est pair mais pas multiple de \(4\) ).
1(b). « \(x>3\Rightarrow x>1\) » : vraie . Réciproque : « \(x>1\Rightarrow x>3\) » : fausse (\(x=2\) ).
1(c). « \(x^2=9\Rightarrow x=3\) » : fausse (contre-exemple \(x=-3\) ). Réciproque : « \(x=3\Rightarrow x^2=9\) » : vraie .
2. Les négations sont :
« il existe au moins un élève qui n'a pas réussi » ;
« aucun entier pair n'est supérieur à \(100\) » ;
« \(x\leqslant0\) ou \(x\geqslant2\) ».
3. Soit \(n\) un entier. S'il est pair, alors \(n(n+1)\) contient le facteur pair \(n\) . S'il est impair, alors \(n+1\) est pair et le produit contient le facteur pair \(n+1\) . Les deux cas couvrent tous les entiers ; donc \(n(n+1)\) est toujours pair.
4. Prouvons la contraposée. Si \(n\) est impair, il existe \(k\in\Z\) tel que \(n=2k+1\) . Alors
\[\begin{aligned}n^2 &= (2k+1)^2\\[.35em]&= 4k^2+4k+1\\[.35em]&= 2(2k^2+2k)+1,\end{aligned}\]
donc \(n^2\) est impair. La contraposée est vraie ; ainsi \(n^2\) pair implique \(n\) pair.
5. Supposons qu'un entier \(n\) soit pair et impair. Il existe alors \(p,q\in\Z\) tels que \(n=2p\) et \(n=2q+1\) . Donc \(2p=2q+1\) , soit \(2(p-q)=1\) . Le membre de gauche est pair, celui de droite impair : contradiction. Un tel entier n'existe pas.
Leçon : une implication et sa réciproque ne se déduisent pas l'une de l'autre en général ; la contraposée est en revanche équivalente à l'implication initiale.
Corrigé 13
Démonstration
def est_premier(n):
if n < 2:
return False
for d in range(2, n): # diviseurs possibles
if n % d == 0:
return False # un diviseur trouve : pas premier
return True
def premiers_jusqua(N):
return [n for n in range(2, N + 1) if est_premier(n)]
est_premier cherche un diviseur entre \(2\) et \(n-1\) : s'il en trouve un, \(n\) n'est pas premier. premiers_jusqua réutilise cette fonction dans une compréhension (programmation modulaire). Par exemple premiers_jusqua(20) renvoie [2, 3, 5, 7, 11, 13, 17, 19].
Corrigé 14
Démonstration
from random import randint
def moyenne_somme(n):
total = 0
for _ in range(n):
total += randint(1, 6) + randint(1, 6) # somme de 2 des
return total / n
D'après la fiche 10, l'espérance de la somme de deux dés vaut \(7\) . Par la loi des grands nombres, moyenne_somme(n) se rapproche de \(\boxed{7}\) quand n devient grand.
Corrigé 15
Démonstration
On parcourt L de la fin vers le début en ajoutant dans une nouvelle liste :
def renverse(L):
R = []
for i in range(len(L) - 1, -1, -1): # de len-1 jusqu'a 0
R.append(L[i])
return R
range(len(L)-1, -1, -1) compte à rebours : indice de départ len(L)-1, on s'arrête avant \(-1\) (donc à \(0\) ), pas de \(-1\) . Par exemple renverse([1,2,3]) renvoie [3, 2, 1].
Corrigé 16
Démonstration
1.
def intersection(A, B):
R = []
for x in A:
if x in B and x not in R: # dans B, et pas deja pris
R.append(x)
return R
On garde un élément de A s'il est aussi dans B (condition x in B) et pas déjà ajouté (évite les doublons). Cela réalise l'intersection d'ensembles, notée \(A\cap B\) en mathématiques. Par exemple intersection([1,2,3,2], [2,3,5]) renvoie [2, 3].
Démonstration · Exercice 16 : produit cartésien
2.
def produit_cartesien(A, B):
couples = []
for x in A:
for y in B:
couples.append((x, y))
return couples
Pour chacun des \(p\) choix de \(x\) , il existe \(q\) choix possibles de \(y\) . Le principe multiplicatif donne donc \(p\times q\) couples. On peut aussi écrire en compréhension :
def produit_cartesien(A, B):
return [(x, y) for x in A for y in B]
Corrigé du problème guidé
Démonstration · Partie A : les briques de base
def moyenne(L):
return sum(L) / len(L)
def maximum(L):
m = L[0]
for x in L:
if x > m:
m = x
return m
def minimum(L):
m = L[0]
for x in L:
if x < m:
m = x
return m
def nb_admis(L):
c = 0
for note in L:
if note >= 10:
c = c + 1
return c
Chaque fonction fait une seule chose et la renvoie. On peut les tester isolément, par exemple maximum([12, 8, 15]) doit donner \(15\) .
Démonstration · Partie B : compréhensions et sélection
# 4. notes >= 10 en une ligne
def admis(L):
return [note for note in L if note >= 10]
# 5. +1 point, plafonne a 20
def ajuste(L):
return [min(note + 1, 20) for note in L]
La compréhension de la question 4 se lit « les notes telles que note \(\geqslant 10\) ». Pour la question 5, min(note + 1, 20) garantit qu'on ne dépasse jamais \(20\) : un \(20\) reste \(20\) , un \(19\) devient \(20\) , un \(12\) devient \(13\) .
Démonstration · Partie C : assemblage modulaire
def bilan(L):
moy = round(moyenne(L), 1)
mini = minimum(L)
maxi = maximum(L)
adm = nb_admis(L)
total = len(L)
return ("Moyenne : " + str(moy) +
" ; Min : " + str(mini) +
" ; Max : " + str(maxi) +
" ; Admis : " + str(adm) + "/" + str(total))
notes = [12, 8, 15, 10, 6, 18, 9]
print(bilan(notes))
# Moyenne : 11.1 ; Min : 6 ; Max : 18 ; Admis : 4/7
7. Pourquoi découper ? Chaque petite fonction peut être testée et corrigée séparément , ce qui rend les erreurs faciles à localiser ; et une fois sûre, chaque fonction se réutilise dans d'autres programmes sans tout réécrire. Un seul long bloc serait illisible et chaque modification risquerait de tout casser.