I1 Revisions 1
I1 Revisions 1
I1 Revisions 1
1 Les types
1 A) Les expressions
Une expression est une suite de caractères définissant une valeur. Pour connaître cette valeur, la machine
doit évaluer l’expression. Voici quelques exemples :
>>> ’str’
>>> 15 ’str’
15 >>> [2,3/1.5]
>>> 15-11 [2, 2.0]
4 >>> 4<2
>>> 2.4+3 False
5.4 >>> 3,4
(3, 4)
Les valeurs possèdent un type : par exemple entier, flottant, booléen, chaîne de caractères, liste,
fonction. Le type détermine les propriétés formelles de la valeur (par exemple, les opérations qu’elle peut subir)
et matérielles (par exemple, la façon dont elle est représentée en mémoire et la place qu’elle occupe).
Pour connaître le type d’une expression après évaluation, il suffit de le demander à Python à l’aide de la
commande type :
>>> type(15-11)
<class ’int’> >>> type(4<2)
>>> type(2.4+3) <class ’bool’>
<class ’float’> >>> type(3,4)
>>> type(’chaine’) Traceback (most recent call last):
<class ’str’> File "<console>", line 1, in <module>
>>> type([2,3/1.5]) TypeError: type() takes 1 or 3 arguments
<class ’list’>
Comme dans la plupart des langages de programmation, une expression en Python est soit :
— une constante comme 2, 8.5 ou ’chaine’ ;
— un nom de variable comme x, i, ou compteur ;
— le résultat d’une fonction appliquée à une ou plusieurs expressions, comme PGCD(8,5) ;
— la composée de plusieurs expressions réunies à l’aide d’opérateurs, comme not a, 3**6, (6+7)*8. Les
parenthèses servent à préciser quels opérateurs doivent être évalués en premier, comme en mathématiques.
On effectue maintenant quelques rappels sur les types simples de manière plus détaillée.
1 B) Entiers (int)
Les entiers (integers en anglais) sont modélisés par le type int.
1 B) a) Constantes
Les entiers permettent de faire des calculs exacts dans la limite de la représentation du nombre en binaire
dans la mémoire de l’ordinateur.
>>> 5**76
132348898008484427979425390731194056570529937744140625
1 B) b) Opérateurs
Les opérateurs sur les entiers sont les suivants :
Opérateur + - * // % **
Signification addition soustraction multiplication division entière modulo exponentiation
On notera bien que a//b renvoie le quotient dans la division euclidienne de a par b.
1 C) Flottants (float)
Les réels sont modélisés par le type float (flottant en anglais).
1 C) a) Constantes
Les flottants sont représentés en mémoire sur 32 ou 64 bits suivant le système sous la forme x = ε × m × 2n .
Sur 64 bits, on a 1 bit pour le signe ε = ±1 , 11 bits pour l’exposant n ∈ Z et 52 bits pour la mantisse m un
nombre décimal compris entre 1 inclus et 2 exclu. On tiendra compte du fait que seul un nombre fini de réels
sont représentables en mémoire, ce qui ne permet pas de faire des calculs exacts. En effet, le plus petit nombre
strictement positif représentable exactement en flottant sur 64 bits est 2−1022 et le plus grand est à 21023 .
1 C) b) Opérateurs
Les opérateurs sur les flottants sont les suivants :
Opérateur + - * / **
Signification addition soustraction multiplication division exponentiation
1 C) c) Règles de priorités
Comme sur les entiers, certains opérateurs sont évalués avant les autres, dans l’ordre de priorité suivant :
1. exponentiation ;
2. multiplication et division ;
3. addition et soustraction.
Les opérateurs de même priorité sont évalués de gauche à droite et les parenthèses permettent de changer ces
priorités.
1 C) d) Conversion automatique
On remarque que la plupart des opérateurs sur les entiers et les flottants sont les mêmes. Lorsqu’on utilise
l’un de ces opérateurs avec des entiers et des flottants, les entiers sont automatiquement convertis en flottants
(on peut forcer la conversion de l’entier n en flottant avec float(n)).
>>> 4*3.1
12.4
>>> 3/4
0.75
>>> 3.0/4
0.75
1 D) Booléens (bool)
1 D) a) Constantes
Les booléens sont essentiels en informatique. Ce type comprend uniquement deux constantes : True (Vrai)
et False (Faux). Ils sont principalement utilisés dans des structures de contrôle.
1 D) b) Opérateurs
Il y a trois opérateurs sur les booléens : not qui correspond à la négation et qui est unitaire (ne prenant
qu’une opérande), and et or qui sont binaires (nécessitant deux opérandes). Voici la table de vérité qui présente
ces différents opérateurs :
a b not a a or b a and b
False False True False False
False True True True False
True False False True False
True True False True True
Pour que a and b soit vrai, il faut que a et b le soient tous les deux. Pour que a or b soit vrai, il suffit que
l’un des deux le soit. Attention, en français, le « ou » peut parfois avoir le sens d’un ou exclusif, comme dans
« fromage ou dessert ». Le or informatique est toujours inclusif : si a et b sont vrais, alors a or b aussi.
Remarque 1.1. Les opérateurs sur les booléens sont analogues aux opérateurs logiques sur les propositions
mathématiques.
1 D) c) Règles de priorité
L’ordre de priorité pour les opérations booléennes est le suivant not ; and ; or. De même que pour les entiers
et les flottants, les opérateurs de même priorité sont évalués de gauche à droite et on peut utiliser des parenthèses.
>>> False and False or True
True
>>> False and (False or True)
False
Pour les évaluations des opérateurs binaires, les deux opérandes des opérateurs de comparaison sont amenés
à un type commun avant l’évaluation de la comparaison (flottant dans le cas d’entier et flottant).
La priorité des opérateurs de comparaison est inférieure à celle des opérateurs arithmétiques : ainsi, l’ex-
pression a==b+c signifie a==(b+c) (on ne peut de toute façon pas additionner un booléen et un flottant).
2 Les variables
2 A) Identificateurs
Un identificateur est une suite de lettres et de chiffres, qui commence par une lettre et qui n’est pas un mot
réservé du langage Python comme if, else, def, return, True notamment. Le caractère _ (underscore, ou
« tiret du 8 ») est considéré comme une lettre. Ainsi, i, j, x, x2, compteur et taille_de_la_liste sont
des identificateurs corrects, contrairement à 4a, x{}, if ou encore taille de la liste. Les identificateurs
diffèrent selon la casse : x et X sont des identificateurs distincts. On s’attachera à éviter l’usage d’accents dans les
identificateurs : ils sont autorisés mais en utiliser soumettrait la bonne exécution d’un programme à l’encodage
des caractères.
2 B) Variables
Une variable est constituée de l’association d’un identificateur à une valeur. Cette association est créée lors
de l’affectation, qui s’écrit sous la forme variable = expression. Attention à ne pas confondre = (affectation)
avec == (test d’égalité). Le mécanisme de l’affectation est le suivant : l’expression à droite du signe égal est
évaluée, puis le résultat de l’évaluation est affecté à la variable.
Après une telle affectation, chaque apparition de la variable ailleurs que dans la partie gauche d’une autre
affectation représente la valeur en question. Cette association entre la variable et la valeur est valable tant qu’il
n’y a pas de nouvelle affectation avec cette même variable.
Exemple 2.1. Compléter les lignes de codes suivantes pour permuter le contenu de x et y. Que contiennent
finalement x et y ?
>>> x = 2**5
>>> y = float(57//8)
Dans la suite, on confondra sans se poser de questions l’identificateur, la variable (l’association de l’identifi-
cateur à une valeur) et la valeur elle-même. Si un identificateur n’a pas été affecté (il n’est donc pas encore un
nom de variable), son emploi ailleurs que dans le membre de gauche d’une affectation est illégale et provoque
une erreur. Par exemple :
>>> print(variable_pas_encore_affectee)
Traceback (most recent call last):
3 Structures de contrôle
3 A) Python et l’indentation
Contrairement à la plupart des autres langages de programmation, Python n’utilise pas d’accolades {. . .} ou
de mots clefs de la forme begin ou end pour délimiter des blocs d’instructions. Tout est basé sur l’indentation :
le fait de laisser une marge blanche devant un bloc d’instructions. Cela allège le code mais il faut faire attention
à respecter des règles strictes :
— une séquence d’instructions est faite d’instructions écrites avec la même indentation ;
— dans une structure de contrôle (instruction conditionnelle if ou boucles for et while) ou dans la définition
d’une fonction, une séquence d’instructions subordonnées doit avoir une indentation supérieure à celle de
la séquence englobante.
— toute ligne écrite avec la même indentation que cette séance englobante marque la fin de la séquence
subordonnée ;
— l’indentation standard est de quatre espaces, ou une tabulation. Les éditeurs convenables, tels que IDLE
ou Pyzo que l’on utilisera, remplacent automatiquement une tabulation par quatre espaces.
L’utilisation de copier/coller, à cause de cette sensibilité extrême de Python à l’indentation, peut s’avérer
hasardeux.
Remarque 3.1. Pour éviter de revenir systématiquement à la ligne entre deux instructions, on peut séparer
les instructions par des points virgules, par exemple x=2 ; y=4, qui réalise successivement l’affectation de x
puis celle de y.
Exemple 3.3. Écrire des lignes de codes renvoyant 10! en utilisant une boucle conditionnelle puis en utilisant
une boucle inconditionnelle.
3 E) Assertion
L’instruction assert de Python est une aide au débogage qui teste une condition. Si la condition est vraie,
votre programme continue à s’exécuter. Mais si la condition d’assertion est fausse, elle lève une exception
AssertionError avec un message d’erreur. L’utilisation appropriée des assertions est d’informer l’auteur du code
d’erreurs irrécupérables dans un programme. Par exemple,
def conversion_masse_poids(M):
assert M>0
g = 9.81
return(M*g)
renverra une erreur lorsque M est négatif ou nul.
4 Fonctions
On appelle fonction tout programme qui, à partir d’un ou plusieurs paramètre(s) appelés entrée(s), calcule
une valeur dépendant de ces paramètres appelée sortie.
Le rôle d’une définition de fonction n’est pas d’exécuter les instructions qui en composent le corps, mais
uniquement de mémoriser ces instructions en vue d’une exécution ultérieure (facultative), provoquée par une
expression faisant appel à la fonction.
4 A) b) L’instruction return
Le corps de la fonction comprend bien souvent une ou plusieurs instructions de la forme return resultat,
où resultat est une expression. Lors du déroulement du corps de la fonction, si une telle instruction est
rencontrée, alors l’expression resultat est évaluée, l’exécution de la fonction est interrompue et la valeur de
resultat prend la place de nom_fonction(e_1,e_2,...,e_k) là où la fonction a été appelée.
Considérons un exemple :
def incremente(x)
return(x+1)
Si on exécute a=incremente(6-2)+9, alors :
— 6-2 s’évalue en 4.
— x prend la valeur 4 dans la fonction.
— x+1 s’évalue en 5, qui est retourné par la fonction.
— incremente(6-2) est donc remplacé par 5.
— incremente(6-2)+9 s’évalue donc en 14, qui est ensuite affecté à la variable a.
4 A) c) Le type « rien »
Si la fonction ne comprend pas de return ou qu’aucun return n’est rencontré lors de l’exécution, la fonc-
tion ne renvoie rien. On dit parfois qu’elle fonctionne uniquement par effets de bord et c’est là une différence
fondamentale avec les mathématiques. Il y a un type pour ça, NoneType, qui comporte une unique valeur, None.
La fonction suivante ne prend aucun paramètre en entrée, se contente d’afficher 4 à l’écran, et ne renvoie rien :
elle agit par effet de bord.
def affiche4():
print(4)
Lors de l’évaluation de a=affiche4(), 4 est affiché à l’écran, on sort de la fonction (car on est arrivé en bas)
et a prend la valeur None. Notez que return seul (sans rien derrière) est souvent fort utile pour interrompre
une fonction. La fonction en question renvoie alors None.
4 A) e) Chaîne de documentation
La chaîne de documentation, ainsi que l’en-tête, sont accessibles lorsqu’on tape help(nom_fonction) :
>>>help(PPCM)
Help on function PPCM in module __main__:
PPCM(a,b)
Avec b>0, renvoie le PPCM de a et b.
Cela fonctionne également avec les fonctions Python.
On parle de passage par valeurs : lors de l’appel à PGCD, les valeurs de a et b sont recopiées et les variables
a et b de la fonction ne sont pas les mêmes que les variables a et b qu’on a définies en dehors de la fonction.
A l’inverse, les variables globales sont des variables créées à l’extérieur de toute fonction. Elles existent depuis
le moment de leur création, jusqu’à la fin de l’exécution du programme. Une variable globale peut être utilisée à
l’intérieur d’une fonction si elle n’est pas le membre de gauche d’une affectation ou le nom d’un paramètre. Par
exemple, la fonction suivante ajoute le contenu de la variable (globale) n au paramètre x et renvoie le résultat
de l’addition.
def ajoute_n(x):
return x+n
>>> n
1
p
X 1 1 1 1 1
Exercice 4.1. Dans cet exercice, on cherche à calculer up = = + + + ··· + où, pour tout
n=0
n! 0! 1! 2! p!
0! = 1 et, pour tout n ∈ N∗ , n! = 1 × 2 × · · · × n.
1. Écrire la fonction factorielle, c’est-à-dire la fonction qui prend en entrée un entier n puis renvoie le produit des
entiers inférieurs à n, soit n × (n − 1) × · · · 2 × 1. On prendra encore la convention suivante : factorielle(0) = 1.
2. Donner un programme Somme convenant, en réutilisant la fonction implémentée dans la question précédente.
3. Lors de l’appel de Somme(p), pouvez-vous compter combien d’opérations arithmétiques effectue la machine ?
Pouvez-vous trouver un programme qui effectue le calcul de up en effectuant moins d’opérations ?
5 Récursivité
5 A) Définition et premiers exemples
Définition 5.1. Un algorithme récursif est un algorithme qui résout un problème en calculant des solutions
d’instances plus petites du même problème.
Remarque 5.2. Une fonction écrite récursivement « s’appelle elle-même ».
En Python, la structure générale est donc la suivante :
def fonction_recursive(parametres):
if ... : #critere d’arret
return ...
else :
return ... #instructions contenant un appel á la fonction récursive
Définition 5.3. Les fonctions non récursives seront appelées fonctions itératives : on parle d’approche impé-
rative.
Un exemple classique est celui de la fonction factorielle. On peut implémenter cette fonction de manière
itérative, en utilisant une boucle for :
def factorielle(n):
x=1
for k in range(1,n+1):
x=x*k
return x
En utilisant la relation de récurrence n! = n × (n − 1)!, on peut aussi utiliser une programmation récursive :
def Factorielle(n):
if n ==0 or n ==1:
return 1
else:
return n*Factorielle(n-1)
L’exemple précédent illustre les trois grands principes que doivent vérifier une fonction récursive :
— une fonction récursive doit comporter un critère d’arrêt qui consiste en la donnée d’un ou plusieurs cas de
base ;
— une fonction récursive doit appeler le critère d’arrêt au bout d’un nombre fini d’étapes (ce qui assure la
terminaison de l’algorithme) ;
— une fonction récursive s’appelle elle-même, mais avec différentes valeurs de (ou des) l’argument(s).
Les appels successifs d’une fonction récursive sont stockés dans une pile : c’est la phase de descente. Une
fois que la close d’arrêt est demandée, les appels sont ensuite dépilés jusqu’à arriver à l’appel initial : c’est la
phase de remontée. Voici la pile d’appel dans l’exemple du calcul de 6! :
Descente Remontée
n = 6 n * 120 = 720
n = 5 n * 24 = 120
n = 4 n * 6 = 24
n = 3 n * 2 = 6
n = 2 n * 2 = 2
n = 1 n = 1
Condition de sortie n == 1
Remarque 5.4. Par défaut, Python limite à 1000 le nombre d’appels récursifs. Tout dépassement provoquera
une erreur RuntimeError: maximum recursion depth exceeded. On peut augmenter la taille de la pile en
utilisant le module sys. Par exemple, pour une pile de taille 2000 :
import sys
sys.setrecursionlimit(2000)
On peut également définir des fonctions mutuellement récursives en prenant soin de les placer l’une après
l’autre dans le script. Dans l’exemple suivant, on placera donc pair avant impair dans le script.
Exemple 5.5.
def pair(n): def impair(n):
if n ==0: if n ==0:
return True return False
else: else:
return impair(n-1) return pair(n-1)
5 B) Exponentiation rapide
Dans cette partie, on s’interdit d’utiliser ** pour calculer une puissance afin de comparer des stratégies pour
pouvoir calculer xn où x est un flottant et n un entier. Pour calculer xn , on peut naïvement écrire que
xn = x × x × · · · × x.
Ainsi, la méthode précédente demande huit multiplications pour calculer 29 . On peut également écrire :
2
29 = 2 × (22 )2
ce qui ne nécessite, en comptant chaque carré comme une seule multiplication, que quatre multiplications. De
façon générale, on peut s’appuyer sur les considérations suivantes :
( k
x2k = x2
k
x2k+1 = x × x2
Exemple 5.6. Écrivons une fonction expo_rapide(x,n), écrite récursivement qui est plus efficace que la
méthode naïve :
Exercice 5.8. Une conjecture classique est que la suite, définie de la manière suivante :
(
un
u0 = N et ∀n ∈ N, un+1 = 3u 2 si un est pair
n +1
2 sinon
atteint toujours 1 en un nombre fini d’étapes (qu’on appelle temps de vol) pour tout entier N ∈ N∗ fixé.
Néanmoins cette conjecture n’est toujours pas démontrée à ce jour. Cette suite est généralement appelée suite
de Syracuse (compressée).
Écrire, de façon itérative, une fonction Syracuse(N), avec une boucle while, qui prend comme argument un
entier N et qui renvoie le plus petit entier n tel que un vaut 1. Refaire ensuite cet exercice sous forme récursive.
5 C) Complexité
Pour traiter un même problème, il existe souvent plusieurs algorithmes. Quand on doit choisir, l’un des critères
est celui du temps d’exécution, qu’on appelle aussi parfois coût de l’algorithme. En effet, le temps d’exécution
conditionne les ressources utilisées (machine sur laquelle on exécutera l’algorithme, consommation électrique...).
Pour un logiciel interactif, par exemple, un temps de réponse court est un élément essentiel du confort de
l’utilisateur. De même, certains programmes industriels doivent être utilisés un grand nombre de fois dans un
délai très court et même un programme qui n’est exécuté qu’une seule fois, par exemple un programme de
simulation écrit pour tester une hypothèse de recherche, est inutilisable s’il demande des mois ou des années de
calcul.
Il existe plusieurs manières de définir la complexité temporelle et celle-ci est liée à la classe d’algorithmes
qu’on analyse.
Chacune des opérations élémentaires suivantes a une certaine durée de traitement :
— l’affectation ;
— les comparaisons ;
— les opérations sur des données numériques ;
Définition 5.9. On appelle modèle à coût constant le fait de supposer que chaque opération élémentaire a une
durée de coût 1.
Dans ce chapitre, on se place dans le cadre d’un modèle à coût constant et on adopte donc la définition
suivante :
Définition 5.10. La complexité d’un algorithme en temps est la somme de tous les temps d’exécution des
différentes opérations effectuées lors de l’exécution.
En général, on cherche à déterminer comment le temps d’exécution d’un algorithme varie en fonction d’un
paramètre qu’on appelle la taille du problème. Le paramètre à considérer dépend du problème considéré. Dans
l’exemple précédent, le temps de recherche des diviseurs d’un entier n dépend de n ; on prendra donc naturelle-
ment cet entier n comme taille du problème. Voici un tableau montrant différents choix possibles de paramètre,
suivant le type d’entrée considéré.
Lorsqu’aucun autre paramètre pertinent n’est disponible, on peut toujours considérer la taille de la représenta-
tion des données passées en entrée comme paramètre.
L’évaluation précise de la complexité d’un algorithme peut s’avérer délicate. Un ordre de grandeur en fonction
des paramètres d’entrée est suffisante pour comparer des algorithmes. On s’appuie sur des notions mathématiques
qu’on rappelle ici.
Définition 5.11.
Soit (un ), (vn ) deux suites réelles non nulles à partir d’un certain rang. On note
1. un = O(vn ) lorsque
∃M > 0, ∃N ∈ N, ∀n > N, |un | 6 M |vn | .
2. un = Θ(vn ) lorsque
∃m, M > 0, ∃N ∈ N, ∀n > N, mvn 6 un 6 M vn .
Considérons un algorithme dépendant d’un paramètre n et notons C(n) le nombre d’opérations effectuées.
On appelle C une fonction de complexité. Vu que seul le terme dominant dans le temps d’exécution est
important pour avoir une idée de l’efficacité de l’algorithme, il est inutile de faire un inventaire précis du nombre
d’opérations effectuées par l’algorithme. On sera ainsi parfois amené à ne compter qu’un type d’opération : celles
qui sont les plus coûteuses. Par exemple, si un algorithme consiste à effectuer essentiellement des multiplications
et des additions, on pourra ne compter que les multiplications, puisqu’on peut imaginer qu’une multiplication
est beaucoup plus coûteuse qu’une addition. On utilisera O () lorsque qu’on voudra seulement une majoration
et Θ pour une évaluation plus précise.
La complexité est donc une mesure d’efficacité d’un algorithme, du coût de l’algorithme en termes de
ressources de l’ordinateur, et on cherchera seulement à avoir une estimation de la fonction de complexité de la
forme suivante qui utilise la notation Θ :
Stocker systématiquement l’état d’une fonction avant chaque appel récursif dans la pile d’appels n’est pas
gratuit, en temps comme en mémoire.
L’idée est de déplacer tous les disques de la première tour sur la troisième tour en respectant les règles suivantes :
— Un seul disque peut être déplacé à la fois,
— Un disque peut uniquement être posé sur un disque de rayon supérieur ou sur un emplacement vide.
Maintenant, raisonnons par récurrence : pour pouvoir déplacer le dernier disque, il est nécessaire de déplacer
les n − 1 disques qui le couvrent sur la tige centrale. Une fois ces déplacements effectués, nous pouvons déplacer
le dernier disque sur la troisième tige. Il reste alors à déplacer les n − 1 autres disques vers la troisième tige.
On peut maintenant en conclure que pour pouvoir déplacer n disques de la tige 1 vers la tige 3 il suffit de
savoir déplacer n − 1 disques de la tige 1 vers la tige 2 puis de la tige 2 vers la tige 3. Autrement dit, il suffit de
généraliser le problème de manière à décrire le déplacement de n disques de la tige i à la tige k en utilisant la
tige j comme pivot. Cela mène à la procédure suivante :
def hanoi(n,i,j,k):
if n==0:
return None
hanoi(n-1,i,k,j)
print(’Deplacer le disque ’+str(n)+’ de la tige ’+str(i)+’ vers la tige ’+str(k))
hanoi(n-1,j,i,k)
En exécutant hanoi(4, 1, 2, 3) on obtient
Deplacer le disque 1 de la tige 1 vers la tige 2
Deplacer le disque 2 de la tige 1 vers la tige 3
Deplacer le disque 1 de la tige 2 vers la tige 3
Deplacer le disque 3 de la tige 1 vers la tige 2
Deplacer le disque 1 de la tige 3 vers la tige 1
Deplacer le disque 2 de la tige 3 vers la tige 2
Deplacer le disque 1 de la tige 1 vers la tige 2
Deplacer le disque 4 de la tige 1 vers la tige 3
Deplacer le disque 1 de la tige 2 vers la tige 3
Deplacer le disque 2 de la tige 2 vers la tige 1
Deplacer le disque 1 de la tige 3 vers la tige 1
Deplacer le disque 3 de la tige 2 vers la tige 3
Deplacer le disque 1 de la tige 1 vers la tige 2
Deplacer le disque 2 de la tige 1 vers la tige 3
Deplacer le disque 1 de la tige 2 vers la tige 3
Si une solution itérative est très compliquée à trouver, la solution récursive s’écrit de manière très simple.
D’une manière générale, il est souvent difficile de trouver une version itérative des algorithmes récursifs où
plusieurs appels récursifs sont nécessaires.
6 Exercices
Exercice 6.1 (Nombre d’occurences). Le nombre d’occurences d’un élément a d’une liste L est le nombre de
fois que cet élément a apparaît dans la liste.
1. Écrire une fonction occurence(a,L) prenant en argument un élément a et une liste L donnant le nombre
d’occurences dd l’élément a dans la liste L.
2. Écrire à nouveau la fonction précédente sous forme récursive. On réfléchira au cas critère d’arrêt et on pourra
utiliser le fait que pour une liste L, L[1:] est la liste L où le premier élément a été supprimé.
Exercice 6.2 (Manipulation de fichiers). Le but de l’exercice est d’analyser un tableau donnant les températures
en Île-de-France depuis 2016. Pour cela, on fournit, sur le site, le fichier temperatures_IDF.csv qui est extrait
des données publiques du site : https://www.data.gouv.fr.
Ce fichier texte représente un tableau comportant quatre colonnes (et plus de 2000 lignes) qui sont séparées
par des virgules. On a, dans l’ordre, une colonne avec la date (au format aaaa-mm-jj puis les températures
minimale, maximale et moyenne sur la journée).
On va ouvrir puis utiliser les données du fichier pour obtenir un graphique.
On ne modifiera pas le fichier texte (c’est-à-dire le tableau) dans cet exercice.
1. Téléchargez le fichier des températures puis placez-vous dans le dossier qui contient ce téléchargement avec
le module os. Exécutez ensuite les lignes suivantes :
fichier = open("temperatures_IDF.csv", ’r’)
lignes = fichier.readlines()
for ligne in lignes:
print(ligne)
2. Écrire une fonction temperature(jour) où jour est une chaîne de caractère de la forme aaaa-mm-jj qui
renvoie la température moyenne du jour. On pourra utiliser split ainsi que la fonction int qui convertit un
entier en chaîne de caractère.
3. Écrire une fonction moyenne(annee) où annee est une chaîne de caractères de la forme aaaa et qui renvoie
la température moyenne du sur l’année. On pourra utiliser split.
4. Tracer un graphique avec en abscisse l’année et en ordonnée la température moyenne annuelle. On obtiendra
le graphe suivant :
5. Avec un jeu de couleur, ajouter sur le graphique précédent les températures minimale et maximale.