Cours
Python
1. Premiers pas : variables, types et opérations
Un programme Python manipule des valeurs rangées dans des variables. Les instructions s'exécutent dans l'ordre où elles sont écrites ; l'affectation s'écrit avec le signe =.
Exercice guidé
Déterminer la valeur affichée par le programme ci-dessous, puis cliquer sur « Exécuter » pour vérifier. Modifier ensuite la première ligne, et elle seule, pour que le programme affiche 13.
SolutionVoir la solutionMasquer
Avec a = 5, la deuxième ligne calcule et range cette valeur dans b.
Python évalue d'abord le membre de droite, avec les valeurs courantes des variables, puis range le résultat dans la variable écrite à gauche. L'instruction a=a+2 remplace ainsi la valeur de a par a+2 :
Ce programme affiche 7, puis True : le test d'égalité s'écrit ==, à ne pas confondre avec l'affectation =. Le caractère # introduit un commentaire, ignoré à l'exécution.
Les types de base
Les types de base
int: les entiers, comme3ou-12;float: les nombres à virgule flottante, comme2.5(attention : point décimal, jamais de virgule) ;bool: les deux booléensTrueetFalse;str: les chaînes de caractères, comme'Bonjour'.
La commande type(x) renvoie le type de x. Les conversions se font avec int(...) et float(...).
Les opérations arithmétiques sont +, -, *, / et ** (puissance).
Division, quotient et reste
La division / renvoie toujours un flottant : 6/3 vaut 2.0. On dispose aussi du quotient entier // et du reste % : 17//5 vaut 3 et 17%5 vaut 2, car .
Une comparaison renvoie un booléen : par exemple 3==2+1 vaut True.
Comparaisons et opérateurs logiques
Une comparaison (==, !=, <, <=, >, >=) renvoie un booléen ; les booléens se combinent avec and, or et not. Le test d'égalité == ne doit pas être confondu avec l'affectation =.
2. Les listes
Une liste regroupe des valeurs numérotées à partir de : dans une liste de longueur , les indices vont de à .
Indices, sous-listes et opérations sur les listes
L[-1]désigne le dernier élément,L[-2]l'avant-dernier ;L[a:b]extrait la sous-liste des indicesaàb-1: la borne droite est exclue ;L1+L2concatène deux listes ;[0]*ncrée une liste de zéros ;list(range(n))donne la liste[0,1,...,n-1];x in Lteste sixappartient à la liste ;L.index(x)renvoie l'indice de sa première occurrence lorsquexest présent.
Le piège de la copie
Le piège de la copie
L'affectation M=L ne crée pas une nouvelle liste : les deux noms désignent la même liste, et modifier l'une modifie l'autre. Pour obtenir une copie indépendante, on écrit M=list(L).
Remarque — listes en compréhension
L'écriture [k**2 for k in range(1,6)] construit directement la liste [1,4,9,16,25]. Cette syntaxe n'est pas exigible mais elle est très répandue dans les sujets ; il faut au moins savoir la lire.
3. Les tests : if, elif, else
L'instruction conditionnelle exécute un bloc seulement si une condition est vraie. Le bloc est délimité par l'indentation (un décalage de quatre espaces) et les deux-points sont obligatoires.
Exemple : afficher la valeur absolue d'un réel saisi au clavier.
La première ligne lit une chaîne de caractères au clavier avec input(), puis la convertit en flottant avec float : c'est la forme habituelle pour saisir un nombre.
La clause else est facultative. Pour enchaîner plusieurs cas exclusifs, on utilise elif :
4. Les boucles
La boucle for
La boucle for et range
for k in range(a,b): répète un bloc pour k allant de a à b-1 : comme pour les listes, la borne droite est exclue. range(n) équivaut à range(0,n).
Premier schéma fondamental, l'accumulateur : calculer .
Méthode — L'accumulateur
On initialise S à avant la boucle, on l'enrichit à chaque tour, on l'exploite après la boucle. Pour un produit, on initialise à .
On peut aussi parcourir directement une liste ou une chaîne de caractères : for x in L: donne à x successivement chaque élément de L.
Deuxième schéma fondamental, la suite récurrente : si et (méthode de Héron, qui converge vers ), le script suivant affiche :
Méthode — La suite récurrente
Partir de u=u0, puis répéter u=f(u) : après tours de boucle, u contient . Une seule variable suffit, chaque tour écrase la valeur précédente ; pour conserver tous les termes, on les range dans une liste (voir la section 7).
La boucle while
Quand le nombre d'itérations n'est pas connu à l'avance, on utilise while : le bloc est répété tant que la condition est vraie. C'est l'outil des recherches de rang d'arrêt, très fréquentes aux concours.
Exemple : pour , afficher le plus petit entier tel que .
Méthode — Le rang d'arrêt
Pour trouver le plus petit rang où une condition cesse d'être vraie, on utilise une boucle while avec un compteur n=n+1. Attention : la condition du while est une condition de poursuite, pas d'arrêt, et il faut toujours s'assurer que la boucle termine — ici parce que tend vers .
Trois schémas à connaître
Accumulateur : initialiser
S=0(ouP=1) avant la boucle, enrichir à chaque tour, exploiter après.Suite récurrente : partir de
u=u0puis répéteru=f(u); après tours,ucontient .Rang d'arrêt : boucle
whileavec un compteurn=n+1, pour trouver le rang minimal où une condition cesse d'être vraie (valeurs approchées de limites, sommes de séries).
5. Les fonctions
Une fonction reçoit des arguments et renvoie un résultat avec return :
Après cette définition, f(3) vaut 10 et on peut composer : f(f(1)) vaut 5.
Un argument peut recevoir une valeur par défaut. Par exemple, def puissance(x,n=2): return x**n permet d'écrire puissance(3) pour obtenir , ou puissance(3,4) pour obtenir . Cette commodité n'est pas exigible, mais sa lecture ne doit pas surprendre dans un sujet.
Une fonction peut prendre plusieurs arguments et renvoyer plusieurs valeurs :
print, return et variables locales
printaffiche,returnrenvoie : une fonction qui se contente d'afficher ne peut pas être réutilisée dans un calcul. Aux concours, on attend presque toujours unreturn.Les variables créées à l'intérieur d'une fonction sont locales : elles n'existent que pendant son exécution.
6. Les bibliothèques : numpy, numpy.random et matplotlib
Python de base ne connaît ni la racine carrée ni le cosinus : ces outils vivent dans des bibliothèques à importer en tête de script.
Les imports du programme
L'écriture import numpy as np importe la bibliothèque sous l'abréviation np ; l'écriture from math import * rend toutes les fonctions de math disponibles sans préfixe.
print(...) affiche une ou plusieurs valeurs. Le module math fournit cos, exp, log, atan, etc. ; numpy fournit les mêmes fonctions, utilisables sur des tableaux.
Tableaux numpy
La bibliothèque numpy manipule des vecteurs et des matrices sous forme de tableaux :
Créer et manipuler un tableau numpy
np.array([1,2,3])crée un vecteur,np.array([[2,7],[5,3]])une matrice donnée ligne par ligne ;np.zeros((n,p)),np.ones((n,p))etnp.eye(n)créent la matrice nulle, la matrice de et la matrice identité ;np.arange(a,b,pas)etnp.linspace(a,b,n)créent des subdivisions régulières (la première par pas fixé, la seconde par nombre de points fixé) ;M[i,j]extrait le coefficient d'indices (numérotés depuis ),M[i,:]la ligne ,M[:,j]la colonne ;n,p = np.shape(M)récupère la taille deM.
Opérations sur les tableaux et produit matriciel
Les opérations +, -, *, /, ** s'appliquent coefficient par coefficient. En particulier A*B n'est pas le produit matriciel : celui-ci s'obtient avec np.dot(A,B), et la transposée avec np.transpose(A).
Enfin, np.sum, np.min, np.max, np.mean, np.median, np.var, np.std et np.cumsum s'appliquent à un tableau entier (somme, minimum, maximum, moyenne, médiane, variance, écart-type et sommes cumulées). Les fonctions usuelles np.exp, np.log, np.sin, np.cos, np.sqrt, np.abs, np.floor agissent élément par élément, et les constantes et s'écrivent np.e et np.pi.
La bibliothèque numpy.linalg (résolution de systèmes, inverse, rang) est détaillée dans la section 11, et numpy.random (échantillons de lois usuelles) dans la section 8.
7. Tracer une courbe, représenter une suite
En Python, pour représenter une fonction sur un segment , on place un nombre fini de points de sa courbe, puis on relie chaque point au suivant par un segment. On choisit pour cela des abscisses dans et on calcule leurs images . Lorsque les abscisses sont assez rapprochées, la ligne brisée obtenue ne se distingue pas à l'œil de la courbe représentative de .
Méthode — Tracer la courbe d'une fonction
On construit le tableau des abscisses, par exemple
x=np.linspace(a,b,N), qui contient réels régulièrement espacés de à , les deux bornes comprises.On calcule le tableau des ordonnées en une seule instruction, comme
y=np.exp(x): les fonctions denumpyagissent élément par élément.On appelle
plt.plot(x,y), une fois pour chaque courbe à superposer, puisplt.show()pour afficher la figure.
Python donne à chaque courbe sa propre couleur. Les commandes plt.grid() et plt.title('...') ajoutent un quadrillage et un titre ; l'option 'o' trace des points isolés, sans les relier.
Exemple : comparer sur la courbe de la fonction exponentielle et sa tangente au point d'abscisse . Cette tangente passe par le point , et son coefficient directeur vaut : son équation est .
La première ligne construit abscisses de à : deux abscisses consécutives sont distantes de . La deuxième ligne calcule d'un coup les ordonnées np.exp(x) et trace la courbe de l'exponentielle. La troisième trace la tangente sans écrire de boucle, car 1+x est lui-même un tableau, calculé élément par élément. Avec np.arange(-2,2,0.02), on obtiendrait des abscisses espacées de elles aussi, mais de à seulement, car la borne droite de np.arange est exclue, comme celle de range.
On remarque que la courbe de l'exponentielle reste au-dessus de sa tangente. Le graphique illustre ainsi l'inégalité , vraie pour tout réel , mais il ne la démontre pas. Pour la démontrer, on étudie la fonction . Sa dérivée est négative sur et positive sur , donc atteint en son minimum, qui vaut . La fonction est donc positive sur , ce qui donne l'inégalité quel que soit le réel .
Représenter les termes d'une suite
Pour une suite, le programme demande de savoir représenter les points . On range les termes dans une liste, puis on les trace avec l'option 'o' (points isolés, sans ligne). Avec la suite de Héron de la section 4 :
Le graphique rend la convergence vers visible dès les premiers rangs.
8. Simuler une expérience aléatoire et étudier un échantillon
rd.random, rd.randint et la borne exclue
rd.random() renvoie un réel uniforme dans et rd.randint(a,b) un entier uniforme dans : contrairement à la fonction homonyme du module standard random, la borne droite est exclue. rd.choice(liste) effectue un tirage uniforme dans une liste et rd.shuffle(liste) mélange la liste sur place.
Le module numpy.random, abrégé en rd, fournit ainsi les briques de base :
Simuler une expérience élémentaire
un lancer de dé équilibré :
rd.randint(1,7);une épreuve de Bernoulli de paramètre : le test
rd.random()<pvautTrueavec probabilité ;un tirage uniforme dans une liste :
rd.choice(L).
Estimer une probabilité par simulation
Si est difficile à calculer, on simule fois l'expérience (avec grand) et on assimile à la fréquence de réalisation de . Cette approche, dite de Monte-Carlo, est confortée par la loi faible des grands nombres.
Exemple : estimer la probabilité d'obtenir au moins un en quatre lancers d'un dé équilibré.
La valeur exacte est ; le script affiche une fréquence proche de cette valeur.
Échantillons avec numpy.random
Échantillons de lois usuelles
Pour simuler d'un coup un échantillon d'une loi usuelle, rd.binomial(n,p,N), rd.geometric(p,N), rd.poisson(lam,N) et rd.randint(a,b,N) renvoient un tableau de simulations, et rd.random(N) un tableau de réels uniformes dans .
La commande plt.hist(ech) trace l'histogramme d'un échantillon ech : on peut ainsi comparer les fréquences observées à la loi théorique, par exemple confronter un échantillon de loi à un échantillon de loi de Poisson .
Indicateurs empiriques
Indicateurs empiriques d'un échantillon
Pour un échantillon ech, les commandes np.mean(ech), np.median(ech), np.var(ech) et np.std(ech) donnent respectivement la moyenne, la médiane, la variance et l'écart-type empiriques. Lorsque la taille de l'échantillon augmente, la loi des grands nombres explique le rapprochement entre moyenne empirique et espérance.
Ici, la moyenne et la variance empiriques sont proches des valeurs théoriques et .
Approche expérimentale de la loi de Gauss
Si avec grand et éloigné de et de , la variable centrée réduite
présente un histogramme proche de la courbe de densité . Cette comparaison est expérimentale : elle sert à visualiser l'approximation gaussienne, pas à la démontrer.
9. La méthode de dichotomie
On cherche une valeur approchée d'une solution de l'équation , lorsque l'on ne sait pas la résoudre de façon exacte. La méthode de dichotomie s'applique à une fonction continue sur un segment, à condition que prenne aux deux extrémités de ce segment des valeurs de signes contraires.
Principe de la méthode
Soit continue sur , avec . Cette condition signifie que l'un des nombres et est nul, ou qu'ils ont des signes contraires. Le théorème des valeurs intermédiaires assure alors l'existence d'au moins un zéro de dans .
On note le milieu de , et on examine le signe de :
si , le théorème des valeurs intermédiaires, appliqué sur , montre que s'annule sur ; on remplace alors par ;
sinon, , donc et sont non nuls et de même signe. Comme , le réel est nul ou de signe contraire à celui de , donc à celui de . Ainsi et s'annule sur ; on remplace alors par .
Dans les deux cas, le nouveau segment vérifie encore : il contient encore une solution, et sa longueur a été divisée par . On répète cette étape. Notons le segment obtenu après étapes, avec . Pour tout , le segment contient une solution de l'équation et a pour longueur . Comme , chacune des bornes et est une valeur approchée de à près.
Critère d'arrêt et nombre d'étapes
On fixe une précision , et on arrête les étapes dès que la longueur est inférieure ou égale à . Comme , cette condition équivaut à , c'est-à-dire à
Le nombre d'étapes est donc connu avant même de lancer le calcul, et la boucle se termine toujours. Ce nombre dépend seulement de la longueur du segment de départ et de la précision demandée, et non de la fonction .
Programme
En Python, une fonction peut recevoir une autre fonction en argument. La fonction dichotomie ci-dessous reçoit ainsi la fonction f dont on cherche un zéro, les bornes a et b du segment de départ et la précision eps. Elle renvoie les bornes du segment final et le nombre n d'étapes effectuées. Le programme l'applique ensuite à deux équations.
Exemple 1. La fonction est dérivable sur , et pour tout réel : est strictement croissante. Elle est aussi continue, et ses valeurs et encadrent . Le théorème de la bijection montre alors que l'équation a exactement une solution dans . Pour la précision , il faut , soit étapes. Le programme affiche en effet (0.68231201171875, 0.682373046875, 14). Les bornes affichées encadrent : . Le réel approche donc à près.
Exemple 2. On prend , dont la dérivée est . Pour tout , on a , donc : est strictement décroissante sur . De plus, car , et car . La fonction s'annule donc une seule fois sur , en , et la dichotomie fournit des valeurs approchées de . Cette fois, la fonction est positive en et négative en . Le programme s'applique sans modification, car le test f(a)*f(m)<=0 porte sur le signe du produit, et non sur le signe de chacun des deux facteurs. Pour , il faut , soit étapes, et le programme affiche (3.1415863037109375, 3.1415939331054688, 17). Le réel est compris entre ces deux bornes, donc il approche à près.
Limites de la méthode
Lorsque l'équation admet plusieurs solutions dans , la méthode en approche une seule, et elle ne dit pas laquelle. Pour approcher une solution précise, on l'isole d'abord dans un segment sur lequel est strictement monotone, comme dans les deux exemples.
La méthode exige un changement de signe. La fonction s'annule en , mais elle ne prend aucune valeur strictement négative, car pour tout réel . Pour un segment , la condition n'est donc vérifiée que si ou annule , c'est-à-dire si l'on connaît déjà un zéro de : la méthode ne sert pas à trouver les zéros de cette fonction.
Chaque étape divise la longueur du segment par seulement. Comme , dix étapes font gagner environ trois décimales.
10. La méthode des rectangles
La fonction est la primitive sur de la fonction qui s'annule en . Par conséquent, : le nombre est l'aire du domaine situé sous la courbe de , au-dessus de l'axe des abscisses, pour allant de à . La méthode des rectangles approche une telle aire par une somme d'aires de rectangles, que l'on calcule avec des additions et des multiplications seulement. Cette section majore l'erreur commise, puis elle confronte cette majoration à la valeur de que donne Python.
On fixe un segment , une fonction de classe sur et un entier . On partage en segments de même longueur , d'extrémités pour . Sur chaque segment , on remplace par la constante , sa valeur en l'extrémité gauche du segment. On obtient la somme des rectangles à gauche
Majoration de l'erreur
La dérivée est continue sur le segment ; on note le maximum de sur ce segment. On fixe , et on note
l'écart, sur le segment , entre l'intégrale de et la contribution du rectangle. Le nombre est l'intégrale sur ce segment de la fonction constante égale à . La valeur absolue de est donc au plus l'aire du domaine compris, pour allant de à , entre la droite horizontale d'équation et la courbe de .
À l'abscisse , ce domaine a pour hauteur . D'après l'inégalité des accroissements finis, vue au chapitre Dérivation, cette hauteur est au plus égale à fois la distance de à . Or, à la même abscisse , le triangle rectangle de sommets , et a précisément pour hauteur . L'aire du domaine est donc au plus celle de ce triangle, dont les côtés de l'angle droit mesurent et :
D'après la relation de Chasles, l'erreur totale est la somme des écarts . L'inégalité triangulaire donne alors
Le majorant devient aussi petit que l'on veut lorsque grandit. La somme approche ainsi l'intégrale de sur , et l'inégalité indique combien de rectangles prendre pour garantir une précision donnée.
ExempleVoir l’exempleMasquer
On applique la méthode à la fonction sur , pour obtenir à près. La fonction est dérivable sur , et sa dérivée y est continue. Pour tout , on a , donc . On peut donc prendre , et comme , la majoration de l'erreur devient
Il suffit que , c'est-à-dire que .
Le programme affiche 0.6936474305598199, puis 0.0005002499998746357. La somme est donc bien une valeur approchée de à près, et l'erreur réelle, environ , vaut la moitié de la majoration. Cette erreur est positive. En effet, est décroissante sur , donc sur chaque segment le rectangle de hauteur contient le domaine situé sous la courbe : la somme dépasse .
La boucle peut aussi s'écrire avec numpy : le tableau a+h*np.arange(n) contient les abscisses , donc h*np.sum(f(a+h*np.arange(n))) calcule la même somme .
11. Résolution des systèmes linéaires
Un système de équations linéaires à inconnues s'écrit sous la forme matricielle , où est la matrice des coefficients, la colonne des inconnues et la colonne des seconds membres. Lorsque est inversible, on multiplie à gauche par : est alors la seule solution. La commande al.solve(A,B) de la bibliothèque numpy.linalg, importée sous l'abréviation al (section 6), calcule cette solution.
ExempleVoir l’exempleMasquer
Le système
s'écrit avec
On donne à Python comme un simple tableau à une dimension :
Le triplet est bien solution, car , et ; la dernière commande fait la même vérification en calculant le produit .
Remarque
Le résultat
array([3., 1., 2.])est un tableau de flottants, comme l'indiquent les points, bien que les coefficients de et de soient entiers. La commandeal.solvecalcule en effet en virgule flottante : la solution qu'elle affiche est en général une valeur approchée de la solution exacte.Pour mesurer cette approximation, on calcule le vecteur , c'est-à-dire
np.dot(A,X)-B. Gardons la matrice et prenons pour second membre . La solution exacte est alors , etal.solverenvoiearray([0.42857143, 0.14285714, -0.14285714]). Pour cette solution affichée , les coefficients de valent , et environ : l'écart est de l'ordre de la précision des flottants.L'équation a une solution et une seule exactement lorsque est inversible, c'est-à-dire lorsque le rang de vaut . La commande
al.matrix_rank(A)donne ce rang ; ici, elle renvoie3. La commandeal.solveest réservée à ce cas.La bibliothèque
numpy.linalgfournit aussial.inv(A), qui calcule l'inverse de , etal.matrix_power(A,n), qui calcule la puissance -ième de .
Savoir-faire exigibles en première année (programme officiel)
Tracer la représentation graphique d'une fonction ou d'une suite (section 7).
Calculer une valeur approchée de la limite d'une suite ou de la somme d'une série, par un rang d'arrêt (section 4 et exercice « Boucle while et premier rang » du TD).
Calculer une valeur approchée de la racine d'une équation (dichotomie, section 9).
Calculer une valeur approchée d'une intégrale par la méthode des rectangles (section 10).
Simuler des expériences aléatoires, des échantillons de lois usuelles, et estimer une probabilité par une fréquence (section 8).
Calculer les indicateurs empiriques d'un échantillon, tracer un histogramme et mettre en évidence expérimentalement une approximation gaussienne (section 8).
Résoudre un système linéaire avec
al.solve(section 11).