Cours Python
Cours Python
Apprendre
Python
pour les sciences
1 Généralités 7
1.1 Programme du cours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.1 Généralités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.2 Variables et types de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.3 Opérations, contrôle, fonctions et modules . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.4 Numpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.1.5 Microprojet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.1.6 Introduction à Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 Prise en main des notebooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1 Les deux modes du notebook : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Changement de mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.3 Mode Commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.4 Mode Edition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.5 Autres commandes utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3 Le langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.1 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.2 Un langage en forte croissance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 Qu’est-ce qu’un langage interprété ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.5 Quelques interpréteurs Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.6 Comment exécuter un programme Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.6.1 Dans la console Python interactive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.6.2 Depuis la console système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.6.3 Dans la console iPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6.4 Au sein d’un notebook Jupyter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6.5 Utilisation d’un IDE (Environnement de développement intégré) . . . . . . . . . . . . 13
1.6.6 Pourquoi un IDE ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7 Applications du langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7.1 Grand public . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.7.2 Mais aussi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.7.3 Intérêt pour les sciences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.7.4 Le Python scientifique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.7.5 Liste non exhaustive de paquets dédiés au Python scientifique : . . . . . . . . . . . . . 15
1.7.6 Python plutôt que Matlab ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.8 Documentation et sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.8.1 La documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.8.2 Les sources de ce support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3
4 TABLE DES MATIÈRES
3.9 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.9.1 Créer ses propres modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.9.2 Imports relatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.9.3 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.9.4 Quelques modules de la stdlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.10 Bonnes pratiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.10.1 Commentez votre code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.10.2 Documentez en utilisant les docstrings . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.10.3 Utilisez les annotations de type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.10.4 Conventions d’écriture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.10.5 Organisez votre code source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.11 Utiliser les environnements de développement intégrés : . . . . . . . . . . . . . . . . . . . . . 81
3.11.1 Utilisez un gestionnaire de versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.11.2 Héberger vos dépôts de sources sur des forges logicielles . . . . . . . . . . . . . . . . . 82
3.11.3 Vérificateurs de code source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.11.4 Tests en Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.11.5 Environnements virtuels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.12 Philosophie du langage : le zen de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.13 Python 3.x vs 2.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.13.1 Différences notables entre Python 2 et Python 3 . . . . . . . . . . . . . . . . . . . . . 83
3.14 Exercice de synthèse : décodage de l’ARN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.14.1 Enoncé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.14.2 Consignes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.14.3 Solution complète . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.15 Exercices complémentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.15.1 Chaines de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.15.2 Récursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5 Microprojet 105
5.1 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
5.1.1 Ouverture du fichier de prévisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
5.1.2 Chargement du fichier json ouvert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.1.3 Exploration des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.1.4 Tracé de la température . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.2 Exercice sur les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
5.3 Exécution avec les widgets ipython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
5.4 Exécution en script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
5.4.1 Utilisation de if __name__ == '__main__': . . . . . . . . . . . . . . . . . . . . . . . 110
5.4.2 Gestion des arguments de la ligne de commande . . . . . . . . . . . . . . . . . . . . . 111
5.5 Utilisation avancée de Spyder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Généralités
7
8 CHAPITRE 1. GÉNÉRALITÉS
1.1.4 Numpy
1.1.5 Microprojet
1.1.6 Introduction à Pandas
Hello world!
Note : - print() est une fonction fournie par python pour afficher du texte à destination de
l’utilisateur. - Entrée [ ]: ou In [ ]: indique le nombre d’exécutions du noyau.
print('Hello world!')
— Vous pouvez vous servir de votre copie d’un notebook pour faire office de bloc-notes en
ajoutant des cellules de texte pour vos commentaires et des cellules de code pour vos essais
de résolution d’exercices.
— Ctrl + S pour sauver vos modifications
Exercice : 1. Ajoutez une cellule de texte ci-dessous (touches B puis M) et insérez une note. 2.
Ajoutez une cellule de code ci-dessous (touche B) et insérez un exemple de code.
1.3.1 Historique
La genèse du langage date de la fin des années 80. Guido van Rossum, alors à l’Institut de Recherche en
Mathématiques et Informatique Hollandais (CWI) à Amsterdam a publié la version 0.9.0 de l’interpréteur
en Février 1991. Il travaille maintenant pour dropbox après 7 ans chez google.
— Plus d’histoire sur wikipedia.
— L’histoire racontée par le créateur lui-même sur son blog sous forme d’anecdotes.
10 CHAPITRE 1. GÉNÉRALITÉS
$ python
Python 3.11.6 (main, Oct 2 2023, 13:45:54) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 2
>>> print(a)
2
>>>
$ python -c 'a=3;print(a)'
Sous windows :
$ python test.py
On peut exécuter directement un fichier python contenant notre code, grâce à l’utilisation du mode script
avec, en rajoutant en première ligne du fichier :
#! python
$ ./test.py
12 CHAPITRE 1. GÉNÉRALITÉS
$ ipython
Python 3.6.2 |Anaconda custom (x86_64)| (default, Sep 21 2017, 18:29:43)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]:
Un exemple d’utilisation
Sauvegarde de l’historique des commandes avec la magic function %save
$ ipython
[...]
In [3]: print(R*6)
Hello you! Hello you! Hello you! Hello you! Hello you! Hello you!
In [5]: quit
- Hello world!
- Hello you!
- Hello you!
- Hello you!
- Hello you!
- Hello you!
- Hello you!
print('Hello world!')
print('- Hello world!')
R = '- Hello you!\n'
print(R*6)
%history
Un grand nombre d’IDE sont disponibles pour Python (cf. la revue wikipedia et la revue wiki.python.org).
Citons simplement :
Dans un IDE, on dispose d’outils intégrés dans une interface (généralement) intuitive :
— débugueur
— analyseur de variables
— outils d’introspection de code
— outils de coloration et de correction syntaxique
— raccourcis d’exécution
— profileurs de code
2. Traitement de données
— langage de haut niveau produisant du code agréable à lire (par opposition à excel, par exemple…)
— nombreux modules spécialisés (algèbre, statistique, traitement d’images, etc.)
— le concept des notebooks Jupyter qui combinent de l’exécution de code, du texte formaté, des
formules mathématiques (via LaTeX), des tracés et du contenu média
1.8. DOCUMENTATION ET SOURCES 15
3. Tracés graphiques :
— tracés 1D, 2D voire 3D
— animations
Alors ?
— Une discussion intéressante : Python vs Matlab
— Un guide de migration : Numpy for Matlab users : guide
— Une table de conversion de la syntaxe : NumPy for MATLAB users : syntax
avec le langage
— Le MOOC de l’INRIA : Python 3 : des fondamentaux à l’utilisation du langage hébergé sur la plateforme
FUN
— La formation du groupe Calcul : ANF “Python avancé en calcul scientifique”
— La formation de Pierre Navaro : Python pour le calcul
16 CHAPITRE 1. GÉNÉRALITÉS
— Le cours de python scientifique de l’institut de science du téléscope spatial : STSCI’s Scientific Python
Course 2015 (en anglais)
en s’entrainant
— Site de tutorat social : Python Tutor
Chapitre 2
— Variables
— Types de données
— Fichiers
variable_x = donnee_x
17
18 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
Julien 23 1.83
Julien a 23 ans, et mesure 1.83 mètre
In [3]: age = 23
print(age)
age = 24
print(age)
23
24
In [4]: print(id(7))
94777227912296
2.1. LANGAGE PYTHON ET SA SYNTAXE 19
x = 7
signifie qu’on nomme l’objet 7 avec la variable x. Autrement dit, x devient une référence vers cet
objet.
In [5]: print(id(7))
x = 7
print(id(x))
y = x
print(id(y)) # y référence le même objet que x
94777227912296
94777227912296
94777227912296
2.1.5 Le type
Les variables n’ont pas de type propre : c’est la donnée qui est typée, pas la variable qui la référence.
Une variable peut donc faire référence à une donnée d’un autre type après une nouvelle affectation.
La fonction type() retourne le type effectif de la donnée passée en paramètre.
<class 'int'>
<class 'str'>
<class 'float'>
<class 'str'>
Une variable peut être initialisée avec des valeurs constantes, comme vu précédement, mais aussi à partir
d’autres variables ou de valeurs retournées par des opérations, des fonctions, etc.
Exemple : La fonction max() retourne le plus grand de ses paramètres.
In [10]: a = 1
b = a
c = a * 2
d = max(a, 2, 3, c)
print(a, b, c, d)
20 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
1 1 2 3
Les variables, une fois définies dans une cellule exécutée, continuent d’exister dans les suivantes car
toutes les cellules sont connectées à la même instance du noyau python.
Note : En cas de redémarrage du notebook, toutes les variables existantes sont détruites, il faut
donc ré-exécuter les cellules qui les définissent si l’on veut de nouveau pouvoir les utiliser.
In [11]: abcd = 1234
1234
Si on veut effacer une variable de l’espace de nom, on peut utiliser l’assertion del.
In [13]: # Cette cellule génère une erreur
a = 2
print(a)
del a
print(a)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 5
3 print(a)
4 del a
----> 5 print(a)
Note : del est aussi utilisé pour enlever des éléments dans des conteneurs modifiables (listes, diction-
naires). Nous aborderons ce sujet plus tard.
Séquences
— Chaines de caractères
— listes
— tuples
2.3. TYPES DE BASE 21
Conteneurs
— Dictionnaires
— Ensembles
Fichiers
In [14]: a = None
print(a)
print(type(a))
None
<class 'NoneType'>
2.3.2 Booléens
Les booléens ne peuvent avoir que deux valeurs :
True, False
False False
False True
False True
False True
22 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
False True
False True
False True
False True
OK
True
<class 'bool'>
Exercice : 1. Supposons que vous soyez malade, mettez Am_I_OK à la valeur False puis réexecutez
la cellule. 2. Essayez avec d’autres types : list, None, nombres, etc…
2.3.3 Numériques
Entiers
La taille est illimitée.
In [17]: # Il n'y a plus de distinction entre les entiers "courts" et les entiers "longs"
entier = 4
print(entier)
print(type(entier))
# Ce nombre nécéssite 131 bits
entier = 1415926535897932384626433832795028841971
print(entier)
print(type(entier))
4
<class 'int'>
1415926535897932384626433832795028841971
<class 'int'>
Ou plus exactement, la taille n’est pas limitée par le langage mais par la mémoire disponible sur le
système.
Note : En python version < 3, il existait deux types distincts int et long…
— On peut utiliser la fonction interne int() pour créer des nombres entiers.
— int() peut créer des entiers à partir de leur représentation sous forme de chaîne de caractères
— On peut aussi spécifier la base :
print(type(entier))
entier = int('0xFF', 16)
print(entier)
print(type(entier))
12
<class 'int'>
13
<class 'int'>
255
<class 'int'>
3.141592653589793
<class 'float'>
3.1415926535897931
<class 'float'>
inf
Flottants
Attention ! Python autorise un affichage plus long que la précision des flottants mais tous les chiffres
après le 16ème chiffre significatif sont faux :
In [20]: # On demande 20 chiffres après la virgule, alors que 16 seulement sont exacts
print('{:.20f}'.format(pi_approx))
3.14159265358979311600
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[21], line 2
1 # Cette cellule génère une erreur
----> 2 print(3.14 / 0)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[22], line 2
1 # Cette cellule génère une erreur
----> 2 print(34 % 0)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[23], line 2
1 # Cette cellule génère une erreur
----> 2 print(27 // 0.0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[24], line 2
1 # Cette cellule génère une erreur
----> 2 print(1 + None)
Complexes
Les nombres complexes, à deux dimensions, peuvent être créés en utilisant le suffixe j à la fin d’un entier
ou réel ou en utilisant la fonction interne complex()
In [25]: c1 = 1 + 2j
print('représentation :', c1)
print(type(c1))
c2 = .3j
print(c2)
représentation : (1+2j)
<class 'complex'>
0.3j
2.4 Séquences
Les séquences sont des conteneurs d’objets où les objets référencés sont ordonnés.
Python supporte nativement trois types de séquences :
2.4. SÉQUENCES 25
janvier février
Les deux formes sont très utiles car elles permettent d’utiliser des guillemets ou des apostrophes dans
des chaînes de caractères de manière simple.
In [27]: arbre = "l'olivier"
print(arbre)
cuisson_pates = "huit minutes (8')"
print(cuisson_pates)
record_100m = 'neuf secondes et 58 centièmes (9"58)'
print(record_100m)
l'olivier
huit minutes (8')
neuf secondes et 58 centièmes (9"58)
Sinon, pour avoir une apostrophe ou un guillemet dans une chaîne de caractères, il faut le faire précéder
d’un \ (backslash). Ce qui est beaucoup moins lisible, mais parfois obligatoire (par exemple une chaîne avec
à la fois des guillemets et des apostrophes).
In [28]: arbre = 'l\'alisier'
pates = '8\''
record = "9\"58"
print(arbre, pates, record)
duel = 'guillemet: " et apostrophes: \' peuvent être utilisés dans une même chaîne...'
print(duel)
multi = '''Dans une "triplequoted" (voire plus loin), on peut (presque) tout utiliser: `"“ ”,'"«»'"' et ça
print(multi)
Caractères spéciaux
Il est possible de définir des chaînes de caractères qui contiennent des caractères spéciaux. Ils sont intro-
duits par des séquences de deux caractères dont le premier est \. On l’appelle le caractère d’échappement.
— retour à la ligne : \n
— tabulation : \t
— backslash : \\
— un caractère unicode avec son code : \uXXXX (où les XXXX sont le code hexadécimal représentant ce
caractère)
26 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
In [29]: print("Une belle présentation, c'est :\n\t- bien ordonné\n\t- aligné\n\t- même s'il y en a plein\nEt c'est
print("Une belle présentation, c'est :")
print('\t- bien ordonné')
print('\t- aligné')
print("\t- même s'il y en a plein\nEt c'est plus joli.")
Chaînes multilignes
Pour écrire plusieurs lignes d’une façon plus lisible, il existe les chaînes multilignes :
Exercice : enlevez le caractère \ de la 2ème ligne dans la cellule ci-dessus, et comparez le résultat
à celui de la cellule de code précédente (3 cellules plus haut)
Les deux formes de délimiteurs sont aussi utilisables : guillemets triples ou apostrophes triples.
multi2 = """a
v
r
i
l l'est aussi"""
print(multi2)
m
a
2.4. SÉQUENCES 27
r
s est un mois "multiligne"
a
v
r
i
l l'est aussi
Unicode
En python 3 , toutes les chaînes de caractères sont unicode, ce qui permet d’utiliser des alphabets
différents, des caractères accentués ou des pictogrammes, etc.
Exemples de caractères spéciaux :
In [33]: normal_str = "chaîne normale: \n est un retour à la ligne, \t est une tabulation"
print(normal_str)
chaîne normale:
est un retour à la ligne, est une tabulation
chaîne RAW: \n est un retour à la ligne, \t est une tabulation
Concaténation
Plusieurs chaînes de caractères contigües sont rassemblées.
azerty
In [35]: a = 'une chaine qui est \t' r'''la somme de \n ''' """plusieurs morceaux..."""
print(a)
On peut utiliser la fonction str() pour créer une chaîne de caractère à partir d’autres objets.
In [36]: a = 23
ch_a = str(a)
print(type(a), repr(a))
print(type(ch_a), repr(ch_a))
a = 3.14
ch_a = str(a)
print(type(a), a)
print(type(ch_a), repr(ch_a))
<class 'int'> 23
<class 'str'> '23'
<class 'float'> 3.14
<class 'str'> '3.14'
On ne peut pas mélanger les guillemets et les apostrophes pour délimiter une chaîne de caractères.
In [39]: variable_1 = 27
variable_2 = 'vingt huit'
ch_modele = 'Une chaine qui contient un {} ainsi que {} et là {}'
ch_modele.format('toto', variable_1, variable_2)
Out[39]: 'Une chaine qui contient un toto ainsi que 27 et là vingt huit'
<class 'str'>
un entier : 27,
une chaîne : Arte,
un flottant avec une précision spécifiée : 3.14
Des hexadécimaux: fe ff 100 101
Des octaux: 376 377 400 401
Des nombres en notation exponentielle 1.844674e+19
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[41], line 5
2 variable_3 = 'une chaine de caracteres'
3 # Exemple d'erreur de type : on fournit une chaîne de caractères
4 # alors que la méthode attend un entier
----> 5 print('on veut un entier : {:d}'.format(variable_3))
In [42]: print("""
Alignons à droite les animaux:
Un animal : {:>8s}.
Un animal : {:>8s}.
Un animal : {:>18s}, qui se croit plus malin que les autres.
Un animal : {:>8s}.
Un animal : {:>8s}.""".format('âne', 'becasse', 'chat', 'dinde', 'elephant'))
f-string
Depuis Python 3.6, il existe une autre syntaxe appelée f-string qui ajoute de la concision et de la lisibilité :
Remarques :
— cette syntaxe n’est pas toujours utilisable
— le code sera incompatible avec python < 3.6
Pour plus d’informations sur le formatage de chaînes de caractères, voir la doc Python correspondante.
2.4.2 Listes
— Une liste est un objet pouvant contenir d’autres objets
— Ces objets, appelés éléments, sont ordonnés de façon séquentielle, les uns à la suite des autres
— C’est un conteneur dynamique dont le nombre et l’ordre des éléments peuvent varier
On crée une liste en délimitant par des crochets [] les éléments qui la composent :
In [45]: L0 = [1, 2]
L1 = []
L2 = [None, True, False, 0, 1, 2**64, 3.14, '', 0+1j, 'abc']
L3 = [[1, 'azerty'], L0]
print(L0, L1)
print(L2)
print(L3)
[1, 2] []
[None, True, False, 0, 1, 18446744073709551616, 3.14, '', 1j, 'abc']
[[1, 'azerty'], [1, 2]]
On peut utiliser la fonction list() pour créer une liste a partir d’autres séquences ou objets.
In [46]: a = list()
b = list('bzzzzzt')
print(a)
print(b)
[]
['b', 'z', 'z', 'z', 'z', 'z', 't']
On accède aux éléments d’une liste grâce à un indice. Le premier élément est indicé 0.
In [47]: print(L)
print(L[0])
print(L[4])
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[48], line 2
1 # Cette cellule génère une erreur
----> 2 print(L[10])
Les listes sont dites muables : on peut modifier la séquence de ses éléments.
Je remplace le deuxième élément :
In [49]: L[1] = 'tomatoes'
print(L)
L[3] = 9
print(L)
Exemples
In [50]: L = ['egg', 'spam', 'spam', 'spam', 'bacon']
print('len() renvoie:', len(L))
L.append('spam') # Ne renvoie pas de valeur
print('Après append():', L)
print('len() renvoie:', len(L))
len() renvoie: 5
Après append(): ['egg', 'spam', 'spam', 'spam', 'bacon', 'spam']
len() renvoie: 6
index() renvoie: 4
Dans les exemples précédents, remarquez la syntaxe qui permet d’appliquer une méthode à un
objet :
objet.methode()
Ici, .methode() est une fonction propre au type de objet. Si .methode() existe pour un autre
type, elle n’a pas forcément le même comportement.
Pour obtenir la liste des méthodes associées aux listes, on peut utiliser la fonction interne help() :
2.4. SÉQUENCES 33
class list(object)
| list(iterable=(), /)
|
| Built-in mutable sequence.
|
| If no argument is given, the constructor creates a new empty list.
| The argument must be an iterable if specified.
|
| Methods defined here:
|
| __add__(self, value, /)
| Return self+value.
|
| __contains__(self, key, /)
| Return key in self.
|
| __delitem__(self, key, /)
| Delete self[key].
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(…)
| x.__getitem__(y) <==> x[y]
|
| __gt__(self, value, /)
| Return self>value.
|
| __iadd__(self, value, /)
| Implement self+=value.
|
| __imul__(self, value, /)
| Implement self*=value.
|
| __init__(self, /, *args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
34 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
| Return len(self).
|
| __lt__(self, value, /)
| Return self<value.
|
| __mul__(self, value, /)
| Return self*value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __repr__(self, /)
| Return repr(self).
|
| __reversed__(self, /)
| Return a reverse iterator over the list.
|
| __rmul__(self, value, /)
| Return value*self.
|
| __setitem__(self, key, value, /)
| Set self[key] to value.
|
| __sizeof__(self, /)
| Return the size of the list in memory, in bytes.
|
| append(self, object, /)
| Append object to the end of the list.
|
| clear(self, /)
| Remove all items from list.
|
| copy(self, /)
| Return a shallow copy of the list.
|
| count(self, value, /)
| Return number of occurrences of value.
|
| extend(self, iterable, /)
| Extend list by appending elements from the iterable.
|
| index(self, value, start=0, stop=9223372036854775807, /)
| Return first index of value.
|
| Raises ValueError if the value is not present.
|
| insert(self, index, object, /)
| Insert object before index.
|
| pop(self, index=-1, /)
| Remove and return item at index (default last).
|
| Raises IndexError if list is empty or index is out of range.
|
2.4. SÉQUENCES 35
| remove(self, value, /)
| Remove first occurrence of value.
|
| Raises ValueError if the value is not present.
|
| reverse(self, /)
| Reverse *IN PLACE*.
|
| sort(self, /, *, key=None, reverse=False)
| Sort the list in ascending order and return None.
|
| The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
| order of two equal elements is maintained).
|
| If a key function is given, apply it once to each list item and sort them,
| ascending or descending, according to their function values.
|
| The reverse flag can be set to sort in descending order.
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| __class_getitem__(…) from builtins.type
| See PEP 585
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __hash__ = None
In [56]: a = ['a', 1] * 5
print(a)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[57], line 3
36 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
Exercice : Manipulez la liste L ci-dessous avec les méthodes associées aux listes.
In [58]: L = ['egg', 'spam', 'spam', 'spam', 'bacon']
# Votre code ci-dessous
2.4.3 Tuples
Les Tuples (ou n-uplets en Français) sont des séquences immuables : on ne peut pas les modifier après
leur création.
On les initialise ainsi :
In [59]: T = ('a', 'b', 'c')
print(T, 'est de type', type(T))
T = 'a', 'b', 'c' # une autre façon, en ommettant les parenthèses
print(T, 'est de type', type(T))
T = tuple(['a', 'b', 'c']) # à partir d'une liste
print(T, 'est de type', type(T))
T = ('a') # ceci n'est pas un tuple
print(T, 'est de type', type(T))
T = ('a',) # Syntaxe pour initialiser un tuple contenant un seul élément
print(T, 'est de type', type(T))
# Syntaxe alternative pour initialiser u n tuple contenant un seul élément.
# Préférez celle avec parenthèses.
T = 'a',
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[61], line 2
1 # Cette cellule génère une erreur
----> 2 T[1] = 'z' # mais on ne peut pas le modifier
Intérêt des tuples par rapport aux listes : - plus rapide à parcourir que les listes - immuables donc
“protégés” - peuvent être utilisés comme clé de dictionnaires (cf. plus loin)
On peut créer des tuples a partir d’autres séquences ou objets grâce à la fonction tuple().
In [62]: a = [1, 2, 3, 'toto']
print(type(a), a)
b = tuple(a)
print(type(b), b)
a = 'azerty'
print(type(a), a)
b = tuple(a)
print(type(b), b)
140577237405696
140577237405696
True
38 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
['spam', 'egg']
['spam', 'egg']
Out[66]: True
Si on modifie la donnée de a, la donnée de b est aussi modifiée !
In [67]: a.append('bacon')
print(a)
print(b)
140576995467200
140576995467200
True
t et u sont deux variables qui référencent le même objet tuple donc leur donnée ne peut être modifiée.
Tout ce qu’on peut faire, c’est affecter une nouvelle valeur :
In [69]: t = 'bacon', 'egg'
Dans ce cas, t référence un nouvel objet alors que u référence toujours l’objet initial :
In [70]: print(id(t))
print(id(u))
print(t is u)
140576997323200
140576995467200
False
('bacon', 'egg')
('spam', 'egg')
Out[71]: False
Exercice : analyser ce qu’il se passe dans cette série d’instructions avec Python Tutor .
2.4. SÉQUENCES 39
In [72]: T = ('a', ['b', 'c']) # le deuxième élément est une liste donc il est muable
print('T =', T)
L = T[1]
print('L =', L)
L[0] = 'e'
print('L =', L)
print('T =', T)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[74], line 2
1 # Cette cellule génère une erreur
----> 2 T[0] = 'A' # Ici, on essaye de modifier le tuple lui même…
Exercice : analyser ce qu’il se passe dans cette série d’instructions avec Python Tutor .
Pour commencer, on extrait de la liste L un nouvel objet liste qui contient tous les éléments de L <=>
copie de liste
In [76]: print(L[0:len(L):1]) # Cette notation est inutilement lourde car :
print(L[::]) # i = 0, j=len(L) et k=1 donc i, j et k peuvent être omis
print(L[:]) # on peut même ommettre le 2ème ":"
Les indices peuvent être négatifs, ce qui permet traiter les derniers éléments :
In [79]: # Je veux exclure le dernier élément :
print(L[0:-1:1]) # Notation complète
print(L[:-1:1]) # Le premier indice vaut i=0, donc on peut l'omettre
print(L[:-1]) # Le pas de slicing vaut 1, donc on peut l'omettre
['est', 'bon']
Note
L[1] n’est pas équivalent à L[1:2], ni à L[1:], ni à L[:1].
Illustration :
In [81]: a = L[1]
print(type(a), a) # Je récupère le deuxième élément de la liste
a = L[1:2]
print(type(a), a) # Je récupère une liste composée du seul élément L[1]
a = L[1:]
print(type(a), a) # Je récupère une liste
a = L[:1]
print(type(a), a) # Je récupère une liste
<class 'str'> le
<class 'list'> ['le']
<class 'list'> ['le', 'Python', 'tout', 'est', 'bon']
<class 'list'> ['Dans']
Exercice : Retourner une liste composée des éléments de L en ordre inverse avec une opération
de slicing. Toute utilisation de [].reverse() ou reversed() est interdite.
In [82]: L = 'Dans le Python tout est bon'.split()
print(L)
# <- votre code ici
Le slicing peut être utilisé pour modifier une séquence muable grâce à l’opération d’affectation.
In [84]: L = 'Dans le Python tout est bon'.split()
print(L)
L[2:4] = ['nouvelles', 'valeurs', 'et encore plus...', 1, 2, 3]
print(L)
Exercice : 1. Découpez l’alphabet en deux parties égales 2. Prenez une lettre sur deux
In [86]: # Votre code ici
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[88], line 3
1 # Cette cellule génère une erreur
2 immuable = 'abcdefgh'
----> 3 immuable[3] = 'D'
Il faut construire une nouvelle chaîne de caractère. En concaténant des morceaux (slices) de la chaîne
originale :
abcDefgh
In [90]: a = list(immuable)
print(a)
a[3] = 'D'
print(a)
print(''.join(a))
True
False
True
In [92]: print(len(immuable))
8
2.6. LES DICTIONNAIRES 43
Les clés peuvent avoir n’importe qu’elle valeur à condition qu’elles soient de type immuable : les listes ne
peuvent pas servir de clés alors que les chaînes de caractères et les tuples le peuvent.
Dans dico, on accède à valeur1 avec la syntaxe dico[cle1].
2.6.1 Un exemple
In [95]: dic_animaux = {'ane': True, 'arbre': False, 'chat': True, 'lune': False, 'humain': True}
cle = 'chat'
valeur = dic_animaux[cle]
print(valeur)
print('{} est un animal: {}'.format(cle, valeur))
# Ou encore
print('{} est un animal: {}'.format('chat', dic_animaux['chat']))
# En utilisant les f-strings :
print(f"{'chat'} est un animal: {dic_animaux['chat']}")
True
chat est un animal: True
chat est un animal: True
chat est un animal: True
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[96], line 2
1 # Votre code ici
----> 2 dic_animaux["toto"]
KeyError: 'toto'
Les différentes manières de créer des dictionnaires, en particulier grâce à la fonction interne dict() :
44 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
Out[97]: True
Accéder à un élément qui n’est pas dans le dictionnaire génère une erreur. Il existe la méthode {}.get()
ou l’opérateur in qui permettent d’éviter ce problème.
In [98]: # Cette cellule génère une erreur
err = a['quatre']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[98], line 2
1 # Cette cellule génère une erreur
----> 2 err = a['quatre']
KeyError: 'quatre'
None
5
Exercice :
1. Modifiez la cellule précédente pour y changer mois_naissance (les 3 premiers caractères de
votre mois de naissance, en anglais). Ré-exécutez la cellule et vérifiez la réponse.
2. Un problème s’est glissé dans la cellule, lequel ?
3. Corrigez-le (il y a plusieurs manières de faire).
Les dictionnaires sont muables.
In [101]: ages = {'albert': 62, 'bob': 34, 'charlie': 1, 'daphne': 67}
print(ages)
print(f'Albert a {ages["albert"]} ans.')
# C'est l'anniversaire de charlie, il a un an de plus...
ages['charlie'] += 1 # equivalent à : ages['charlie'] = ages['charlie'] + 1
print(ages)
# Bob est parti, enlevons-le
del ages['bob']
print(ages)
2.7. LES ENSEMBLES 45
— Savoir si une clé est présente dans un dictionnaire est une opération rapide. On utilise, comme pour
les séquences, l’opérateur in.
— La fonction interne len() est utilisable pour savoir combien d’objets sont référencés dans le dictionnaire.
On peut itérer sur les clés ou les objets référencés, ou vider un dictionnaire, en comparer deux, etc.
Pour plus d’informations sur les dictionnaires, voir ici.
Exercice :
1. Créez un dictionnaire qui va traduire des chiffres (de 1 à 3) écrits en toutes lettres entre
deux langues. Par exemple : trad_num['un'] → 'one'
2. Modifiez ce dictionnaire, pour qu’il fonctionne dans les deux sens de traduction (Fr → En
et En → Fr)
3. Modifiez ce dictionnaire, pour qu’il fonctionne aussi avec les chiffres sous forme d’entiers.
Par exemple : trad_num[1] → 'un'
ensemble = set(iterable)
Où iterable peut être n’importe quel objet qui supporte l’itération : liste, tuple, dictionnaire, un autre
set (pour en faire une copie), vos propres objets itérables, etc…
Tout comme pour les dictionnaires, l’opérateur in est efficace.
46 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
2.7.1 Exemples
In [105]: tupl1 = ('un', 'un', 'deux', 1, 3)
list1 = [1, 1, 2]
a = set(tupl1)
b = set(list1)
print(a, b)
print(a, b)
Des opérations supplémentaires sont possibles sur des ensembles. Elles sont calquées sur les opérations
mathématiques :
— union
— intersection
— etc…
In [106]: print('intersection :', a & b)
print('union :', a | b)
intersection : {1}
union : {1, 2, 3, 'deux'}
2.8 Fichiers
2.8.1 Ouverture
L’instruction :
f = open('interessant.txt', mode='r')
ouvre le fichier interessant.txt en mode lecture seule et le renvoie dans l’objet f.
— On peut spécifier un chemin d’accès complet ou relatif au répertoire courant
— Le caractère de séparation pour les répertoires peut être différent en fonction du système d’exploitation
(/ pour unix et \ pour windows), voir le module os.path ou mieux la bibliothèque pathlib.
2.8.2 Fermeture
On ferme le fichier f avec l’instruction :
f.close()
— f.readlines() : retourne toutes les lignes de f sous la forme d’une liste de chaînes de caractères.
In [108]: f = open('exos/interessant.txt', mode='r')
lignes = f.readlines()
f.close()
print(f'"lignes" est un objet de type {type(lignes)} contenant {len(lignes)} éléments:')
print(lignes)
Note : du point de vue du système, rien n’est écrit dans le fichier avant l’appel de f.close()
— f.writelines(ma_sequence) : écrit la séquence ma_sequence dans f en mettant bout à bout les
éléments
In [110]: sequence = ['Je sais ajouter\n', 'du texte\n', 'avec Python !\n']
f = open('pas_mal.txt', mode='a')
# mode 'a' : on ajoute à la fin du fichier
f.writelines(sequence)
f.close()
%pycat pas_mal.txt
48 CHAPITRE 2. VARIABLES ET TYPES DE DONNÉES
Exercice :
1. écrire le contenu de la liste mystere dans le fichier coded.txt puis fermer ce dernier
2. lire le fichier coded.txt et le stocker dans une chaine coded
3. Décoder la chaîne coded avec les instructions suivantes :
import codecs
decoded = codecs.decode(coded, encoding='rot13')
4. écrire la chaine decoded dans le fichier decoded.txt et fermer ce dernier
5. visualiser le contenu du fichier decoded.txt dans un éditeur de texte
— Opérateurs
— Structures de contrôle
— Fonctions
— Exceptions & gestionnaires de contexte
— Compréhensions de listes & expressions génératrices
— Modules
— Bonnes pratiques
3.1 Opérateurs
3.1.1 Arithmétiques
+, -, *, /, //, %, **
Particularités de la division
In [1]: # Avec des nombres entiers
print(16 / 3) # Quotient de la division euclidienne (produit un réel)
print(16 // 3) # Quotient de la division euclidienne (produit un entier)
49
50 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
5.333333333333333
5
1
5.333333333333333
5.0
1.0
Puissance
In [2]: print(2**10)
# On peut aussi utiliser la fonction pow() du module math, mais celle-ci renvoie un réel.
import math
print(math.pow(2, 10))
1024
1024.0
3.1.2 Logiques
and, or, not
True
False
False
True
True
False
Exercice : Modifiez les valeurs True et False dans la cellule précédente, pour visualiser le
fonctionnement de ces opérateurs.
3.1.3 Comparaison
python ==, is, !=, is not, >, >=, <, <= L’évaluation de ces opérateurs retourne une valeur boo-
léenne.
In [6]: print(2 == 2)
print(2 != 2)
print(2 == 2.0)
print(type(2) is int)
True
False
True
True
On peut utiliser ces opérateurs avec des variables et des appels à des fonctions.
In [7]: x = 3
print(1 > x)
y = [0, 1, 42, 0]
print(x <= max(y))
print(x <= min(y))
False
True
False
On peut chaîner ces opérateurs, mais ils fonctionnent en mode court-circuit et l’opérande centrale n’est
évaluée qu’une seule fois.
In [8]: x = 3
print(2 < x <= 9) # équivalent à 2 < x and x <= 9
True
Attention : comparer des types non numériques peut avoir des résultats surprenants.
True
True
False
In [10]: # Listes
print([1, 2, 3, 4] > [42, 42])
print([666] > [42, 42])
52 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
False
True
Attention : comparer des types incompatibles peut avoir des résultats surprenants.
In [11]: # Cette cellule génère des erreurs
print("chaîne:\t", "a" < 2)
print("liste:\t", ["zogzog"] > 42)
print("vide:\t", [] > 1)
print("tuple:\t", [23, 24] >= (23, 24))
print("dict:\t", [23, 24] >= {23: True, 24: "c'est pas faux"})
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[11], line 2
1 # Cette cellule génère des erreurs
----> 2 print("chaîne:\t", "a" < 2)
3 print("liste:\t", ["zogzog"] > 42)
4 print("vide:\t", [] > 1)
Attention, l’égalité de valeur n’implique pas forcément que l’identité des objets comparés est la même.
In [12]: a = [] # a est une liste vide
b = [] # b est une AUTRE liste vide
True
False
id(a) = 140298911160384
id(b) = 140298911265600
Mais, comme vu précédemment, des variables différentes peuvent référencer le même objet.
In [14]: c = a
print(a == c) # test de valeur
print(a is c) # test d'identité
True
True
0b1000011
le 1er bit vaut 1
le 2ème bit vaut 1
le 3ème bit vaut 0
le 7ème bit vaut 1
75
11
Exercice : Retournez une chaîne de caractères représentant le nombre contenu dans x écrit en
notation binaire. Par exemple :
In [16]: x = 7
# votre code ici
In [18]: a = 4
a += 1 # <=> a = a + 1
print(a)
a //= 2
print(a)
a **= 3
print(a)
a %= 2
print(a)
5
2
54 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
8
0
2
2.0
(6+4j)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[20], line 4
2 a = 1
3 b = "1"
----> 4 a + b
Exercice :
Sans toucher au +, corrigez la ligne 4 de la cellule ci-dessus afin d’afficher :
1. la chaîne '11'
2. l’entier 2
3. l’entier 11
In [21]: a = 1
b = "1"
a + b
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[21], line 3
1 a = 1
2 b = "1"
----> 3 a + b
toutes
les
lignes
au même niveau d'indentation forment un bloc de code
et quand on remonte, on "termine" un bloc de code
Exercice : changez le True en False, et observez quelles lignes de code ne sont plus exécutées.
3.2.2 pass
En cas de besoin d’un bloc de code qui ne fait rien, on utilise le mot clé pass (équivalent à NOP ou
NO-OP)
56 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
(à ne pas exécuter dans une cellule sous peine de bloquer le noyau de ce notebook)
if test1:
<bloc d instructions 1>
elif test2:
<bloc d instructions 2>
else:
<bloc d instructions 3>
c'est vrai!
In [25]: if False:
print("je suis caché!")
else:
print("mais moi je suis en pleine lumière...")
In [26]: # Pour cet exemple, on itère sur les éléments d'un tuple (cf. boucle for plus loin)
for position in 2, 9, 3, 1, 8:
if position == 1:
print(position, "Or")
elif position == 2:
print(position, "Argent")
elif position == 3:
print(position, "Bronze")
else:
print(position, "Vestiaires")
2 Argent
9 Vestiaires
3 Bronze
1 Or
8 Vestiaires
petit
3.3. BOUCLES 57
Exercices :
1. Editez la cellule pour y mettre votre taille et exécutez-la pour savoir si vous êtes grand ou
petit.
2. Gérez le cas des gens de taille moyenne.
3.3 Boucles
Les boucles sont les structures de contrôle permettant de répéter l’exécution d’un bloc de code plusieurs
fois.
while <condition>:
<bloc 1>
<bloc 2>
Tant que <condition> est True, le <bloc 1> est exécuté, quand la condition passe à False, l’exécution
continue au <bloc 2>.
In [29]: compteur = 3
while compteur > 0:
print("le compteur vaut :", compteur)
compteur -= 1
print("le compteur a été décrémenté 3 fois et vaut maintenant", compteur)
le compteur vaut : 3
le compteur vaut : 2
le compteur vaut : 1
le compteur a été décrémenté 3 fois et vaut maintenant 0
Exercice :
C’est la soirée du réveillon. Ecrivez une boucle while qui décompte les secondes à partir de 5
pour souhaiter la bonne année.
Allez voir par ici pour passer le temps…
Exercice : Rajoutez des invités à la fête. Vérifiez que tout le monde est accueilli correctement.
In [33]: # Maintenant, si nous avons reçu des réponses à notre invitation, utilisons un dictionnaire :
invites = {"Aline": True, "Bernard": False, "Céline": True, "Dédé": True}
for personne, presence in invites.items():
if presence:
print(f"Bonjour {personne}, bienvenue à la soirée de gala !")
else:
print(f"Malheureusement, {personne} ne sera pas avec nous ce soir.")
print("Maintenant, tout le monde a été bien accueilli ou excusé.")
Bonjour Aline, bienvenue à la soirée de gala !
Malheureusement, Bernard ne sera pas avec nous ce soir.
Bonjour Céline, bienvenue à la soirée de gala !
Bonjour Dédé, bienvenue à la soirée de gala !
Maintenant, tout le monde a été bien accueilli ou excusé.
Il existe une forme raccourcie pour faire ce genre de choses, la fonction interne enumerate()
In [35]: nombres = [2, 4, 8, 6, 8, 1, 0]
impairs = nombres[:] # On copie la liste nombres
for i, nombre in enumerate(nombres):
impairs[i] = bool(nombre % 2)
# Les impairs
print(impairs)
[False, False, False, False, False, True, False]
3.3. BOUCLES 59
Note
La fonction interne range() retourne un itérateur. C’est un objet qui se comporte comme une liste sans
pour autant allouer la mémoire nécessaire au stockage de tous ses éléments. Le coût de création d’une vraie
liste augmente avec sa taille (son empreinte mémoire aussi !).
— une liste (ou un tuple) contient des données
— un itérateur possède la méthode qui permet de calculer l’élément suivant dans une boucle for.
Note de la note
En Python version 2.x, Il existait deux versions de cette fonctionnalité : range() et xrange(). La première
retournait une vraie liste, allouée complètement, alors que xrange() retournait un itérateur.
<class 'range'>
range(0, 3)
<class 'list'>
[0, 1, 2]
In [37]: compteur = 3
while True: # Notre boucle infinie
compteur -= 1
print(f"Dans la boucle infinie! {compteur = }")
if compteur <= 0:
break # On sort de la boucle while immédiatement
print(f"On continue, {compteur = }")
print("C'était pas vraiment une boucle infinie...")
En cas d’imbrication de plusieurs boucles, l’instruction break sort de la plus imbriquée (la plus proche).
i, j = (1, 1)
i, j = (1, 2)
i, j = (1, 3)
60 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
i, j = (1, 4)
i, j = (3, 1)
i, j = (3, 2)
i, j = (3, 3)
i, j = (3, 4)
In [39]: compteur = 9
while compteur > 0:
compteur -= 1
if compteur % 2:
compteur /= 2
print("impair, on divise :", compteur)
continue # retourne immédiatement au début de la boucle
print("pair, RAS")
print("c'est fini...")
pair, RAS
impair, on divise : 3.5
impair, on divise : 1.25
impair, on divise : 0.125
impair, on divise : -0.4375
c'est fini…
3.4 Fonctions
Les fonctions permettent de réutiliser des blocs de code à plusieurs endroits différents sans avoir à copier
ce bloc.
En python, il n’y a pas de notion de sous-routine. Les procédures sont gérées par les objets de type
fonctions, avec ou sans valeur de retour.
On distingue :
— les fonctions avec return des fonctions sans return
— les fonctions sans arguments (pour lesquelles () est vide) des fonctions avec arguments (arg1, arg2,
...)
<nom fonction>(arg1, arg2, ...) est appelé signature de la fonction.
Exercice : Ecrivez une fonction nommée rien qui ne fait rien et appelez là deux fois.
In [42]: # Votre code ici
print("1er appel:")
func() # 1er Appel de la fonction : la valeur retournée n'est pas utilisée
print("2eme appel:")
ret_val = func() # Le retour du 2eme appel est stocké
print("La fonction func() nous a renvoyé la valeur:", ret_val)
1er appel:
2eme appel:
La fonction func() nous a renvoyé la valeur: I'm happy
Exercice : Ecrivez une fonction nommée eloge_de_rien qui retourne la chaine de caractères
rien. Appelez-là et affichez sa valeur de retour.
In [45]: # Votre code ici
Important : l’instruction return provoque une sortie de la fonction. Dans le code suivant, la ligne qui
appelle la fonction print() n’est pas exécutée.
In [47]: def func():
return "je sors"
print("après return")
func()
Pour utiliser cette fonction avec diverses valeurs, il suffit de l’appeler plusieurs fois :
In [49]: print(somme(1, 2))
print(somme(4, 7))
print(somme(2 + 2, 7))
print(somme(somme(2, 2), 7))
3
11
11
11
Exercice : - Définissez une fonction nommée chevalier qui prend un paramètre n et qui affiche
n fois (avec print()) la chaîne de caractères Nee! - appelez cette fonction pour vérifier que
chevalier(3) dit bien Nee! trois fois comme il convient !
Voici quelques exemples montrant comment cette fonction doit se comporter :
chevalier(1)
Nee!
chevalier(3)
Nee!Nee!Nee!
chevalier(6)
Nee!Nee!Nee!Nee!Nee!Nee!
In [50]: def chevalier(n):
# Votre code ici
pass
Exercice : Ecrivez une autre fonction, nommée chevalier_ret : - qui prend 2 paramètres :
un entier n et un booléen - qui retourne une chaine de caractères de la chaîne nee! ou NEE! en
fonction du paramètre booléen, chaîne répétée n fois.
Appelez cette fonction et affichez sa valeur de retour.
Voici quelques exemples montrant comment cette fonction doit se comporter :
a = chevalier_ret(1, True)
print(a)
NEE!
print(chevalier_ret(3, False))
nee!nee!nee!
print(chevalier_ret(6, True))
NEE!NEE!NEE!NEE!NEE!NEE!
3.4. FONCTIONS 63
NEE!
nee!nee!nee!
NEE!NEE!NEE!NEE!NEE!NEE!
print(somme(1, 2))
Si sa valeur n’est pas spécifiée lors de l’appel, le paramètre y prend la valeur par défaut (ici : 1)
In [57]: print(somme(4))
Note : Les arguments ayant une valeur par défaut doivent être placés en dernier.
Si les arguments sont explicitiment nommés lors de l’appel, leur ordre peut être changé :
print(diff(4, 7))
print(diff(y=7, x=4))
-3
-3
64 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
<class 'tuple'>
("n'importe", 'quel nombre et type de', 'paramètres', 5, [1, 'toto'], None)
Arguments nommés dans un dictionnaire On définit une fonction dont l’argument est **kwargs :
In [61]: def fonc(**kwargs):
# kwargs est un dictionnaire :
print(type(kwargs))
# ses éléments sont les arguments nommés passés lors de l'appel
print(kwargs)
<class 'dict'>
{'x': 1, 'y': 2, 'couleur': 'rouge', 'epaisseur': 2}
print("appel 1")
fonc(3)
print("appel 2")
fonc(3, "bacon")
print("appel 3")
fonc(2, "spam", "egg", x=1, y=2, couleur="rouge", epaisseur=2)
appel 1
n = 3
args = ()
kwargs = {}
appel 2
n = 3
args = ('bacon',)
kwargs = {}
appel 3
n = 2
args = ('spam', 'egg')
kwargs = {'x': 1, 'y': 2, 'couleur': 'rouge', 'epaisseur': 2}
3.4. FONCTIONS 65
Remarques :
— les noms args et kwargs ne sont que des conventions (à respecter, toutefois !), seul le caractère * est
déterminant
— l’ordre (arg1, arg2, ..., *args, **kwargs) doit être strictement respecté
Packing/unpacking
— La syntaxe *args dans la définition de la fonction correspond à une opération de packing : Python
transforme une séquence de variables en tuple.
— L’inverse existe : ça s’appelle l’unpacking.
— Le packing/unpacking se pratique déjà par la manipulation des tuples :
def func2():
print(f"Dans func2(), {a = }")
a = 2
func1()
func2()
print(f"Dans l'espace englobant, {a = }")
Dans func1(), a = 1
Dans func2(), a = 2
Dans l'espace englobant, a = 2
2ème exemple
On veut illustrer le mécanisme de portée des variables au sein des fonctions :
a = 2
print(f"Avant func() : {a = }")
func()
print(f"Après func() : {a = }")
Avant func() : a = 2
Dans func() : a = 1
Après func() : a = 2
Les variables définies localement à l’intérieur d’une fonction sont détruites à la sortie de cette fonction.
Ici, la variable bbb n’existe pas hors de la fonction func(), donc Python renvoie une erreur si on essaye
d’utiliser bbb depuis l’espace englobant :
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[69], line 2
1 # Cette cellule génère une erreur
----> 2 print(bbb)
In [70]: a = 1
b = eval("a + 1")
print(f"{type(b) = } ; {b = }")
---------------------------------------------------------------------------
StdinNotImplementedError Traceback (most recent call last)
Cell In[71], line 1
----> 1 reponse = input("Ca va ? ")
3 if reponse.lower() in ("o", "oui", "yes", "y", "ok", "da", "jawohl", "ja"):
4 print("Supercalifragilisticexpialidocious")
StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
In [72]: print(list(range(10)))
print(list(range(5, 10, 2)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[5, 7, 9]
Exercice 1
Ecrire une fonction stat() qui prend en argument une liste d’entiers et retourne un tuple contenant : -
la somme - le minimum - le maximum
des éléments de la liste
Soit une fonction boule() capable d’accrocher une boule de couleur à la position (x, y) d’un sapin.
Exercice inspiré du Mooc de l’INRIA Python : des fondamentaux à l’utilisation du langage
Ecrire une fonction wrapper boule_or() qui crée des boules dorées en appelant la fonction boule().
Dans le futur, on souhaite modifier la fonction boule() pour lui faire accepter un nouvel argument rendu
(brillant, mat, etc.). La fonction boule_or() devra continuer à fonctionner après cette modification
de la fonction boule() et intégrer la nouvelle fonctionnalité rendu sans qu’il soit nécessaire de modifier
boule_or().
Vérifier que votre fonction boule_or() marche encore et gère la nouvelle fonctionnalité :
3.5 Exceptions
Pour signaler des conditions particulières (erreurs, évenements exceptionnels), Python utilise un méca-
nisme de levée d’exceptions.
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
Cell In[80], line 2
1 # Cette cellule génère une erreur
----> 2 raise Exception
Exception:
Ces exceptions peuvent embarquer des données permettant d’identifier l’évenement producteur.
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
Cell In[81], line 2
1 # Cette cellule génère une erreur
----> 2 raise Exception("Y a une erreur")
La levée d’une exception interrompt le cours normal de l’exécution du code et “remonte” jusqu’à l’endroit
le plus proche gérant cette exception.
Pour intercepter les exceptions, on écrit :
3.5. EXCEPTIONS 71
try:
<bloc de code 1>
except Exception:
<bloc de code 2>
In [82]: try:
print("ici ca fonctionne")
# ici on détecte une condition exceptionnelle, on signale une exception
raise Exception("y a un bug")
print("on n'arrive jamais ici")
except Exception as e:
# L'exécution continue ici
print(
f"ici on peut essayer de corriger le problème lié à l'exception : Exception({e})"
)
print("et après, ça continue ici")
ici ca fonctionne
ici on peut essayer de corriger le problème lié à l'exception : Exception(y a un bug)
et après, ça continue ici
def b():
print("b() commence")
a()
print("b() finit")
try:
b()
except Exception as e:
print("l'exception vous envoie le message :", e)
b() commence
l'exception vous envoie le message : coucou de a()
3.5.1 Exercice
Ecrivez une fonction openfile() :
— qui demande à l’utilisateur un nom de fichier à ouvrir
— qui gère correctement les fichiers inexistants.
— qui affiche la première ligne du fichier ouvert
— qui retourne une valeur booléenne indiquant que le fichier a été ouvert ou non.
except FileNotFoundError:
return False
print(openfile("exos/interessant.txt"))
True
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[87], line 2
1 # Cette cellule génère une erreur
----> 2 print(fichier_ouvert.read())
Exercice : Reprenez le code de l’exercice précédent, et utilisez with pour ne pas avoir à utiliser
la méthode close().
Il est possible de créer de nouveaux gestionnaires de contexte, pour que vos objets puissent être utilisés
avec with et que les ressources associées soient correctement libérées.
Pour plus d’informations sur la création de gestionnaires de contexte, voir la documentation.
3.7. LES COMPRÉHENSIONS DE LISTES 73
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
On veut maintenant une liste ne contenant que les éléments pairs de la liste Liste1.
In [91]: ListePaire = []
for i in Liste1:
if (i % 2) == 0:
ListePaire.append(i)
print(ListePaire)
[0, 2, 4, 6, 8]
[0, 2, 4, 6, 8]
Cette concision peut être utile, mais n’en abusez pas, si vous commencez à avoir une compréhension de
liste trop complexe à écrire en une simple ligne, utilisez plutôt des boucles et conditions explicites.
Plus d’informations dans ce tutoriel.
In [94]: print(generateur_pairs)
Pour visualiser son comportement, on peut l’utiliser pour créer une liste :
In [95]: print(list(generateur_pairs))
[0, 2, 4, 6, 8]
3.9 Modules
— Python fournit un système de modularisation du code qui permet d’organiser un projet contenant de
grandes quantités de code et de réutiliser et de partager ce code entre plusieurs applications.
— L’instruction import permet d’accéder à du code situé dans d’autres fichiers. Cela inclut les nombreux
modules de la bibliothèque standard, tout comme vos propres fichiers contenant du code.
— Les objets (variables, fonctions, classes, etc.) du module sont accessibles de la manière suivante :
module.variable
module.fonction(parametre1, parametre2, ...)
Ou plus généralement :
module.attribut
In [96]: # Pour utiliser les fonctions mathématiques du module 'math'
import math
print(f"{math.pi:.2f}")
print(f"{math.sin(math.pi):.2f}")
3.14
0.00
import mon_module
shutil.copy(
"exos/mon_module.py", "."
) # On copie le fichier dans le répertoire d'exécution du notebook
%pycat mon_module.py
print(mon_module.ma_variable)
mon_module.ma_fonction() # On accède ainsi à l'attribut ma_fonction() du module mon_module
3.9. MODULES 75
27
un appel à ma_fonction()
mm.ma_fonction()
un appel à ma_fonction()
ma_fonction()
un appel à ma_fonction()
ma_fonc()
un appel à ma_fonction()
Note :
Dans le code :
import mon_module
[...]
import mon_module
Le deuxième import n’a pas d’effet car le module n’est importé qu’une seule fois au sein d’une même
instance Python. Toutefois, il existe des moyens de le réimporter de force avec la bibliothèque importlib.
Exercice : Modifiez le code contenu dans le fichier mon_module.py, et reexécutez la cellule ci-
dessus. Que remarquez-vous ?
— Cas 2.a : on veut aller chercher du code dans un autre projet python qui n’est pas installé dans
l’environnement courant
— Cas 2.b : on travaille sur un gros projet structuré en modules stockés dans une arborescence de
sous-répertoires.
76 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
sys.path.append("./exos/ext_dir")
print(sys.path)
Cas 2.b : un projet structuré en sous-répertoires Dans ce cas, on parle de paquets (packages) et de
sous-paquets :
— n’importe quel répertoire contenant un fichier __init__.py est un paquet python
— chaque sous-répertoire est un sous-paquet du répertoire (ou paquet) parent
— une arborescence de paquets permet d’organiser le code de manière hiérarchique.
— On accède aux sous-paquets avec la notation :
import paquet.sous_paquet.sous_sous_paquet...
exos
[...]
��� sous_paquet
� ��� __init__.py
� ��� module_a.py
� ��� module_b.py
��� sous_paquet2
� ��� __init__.py
� ��� module_c.py
[...]
# On appelle fonction()
exos.sous_paquet.module_a.fonction()
3.9. MODULES 77
ou encore :
# On appelle fonction()
module_a.fonction()
Remarque
Si __init__.py existe, le code qu’il contient est exécuté lors de l’import du paquet.
module_b.fonction()
exos/sous_paquet2/module_c.py
exos/sous_paquet/module_b.py
en utilisant la syntaxe :
module_c.fonction()
module_c.module_b.fonction()
3.9.3 Exercice
1. dans le répertoire exos/sous_paquet2/ copiez la définition de la fonction boule() (cf. Section
??) dans un fichier nommé deco.py
def boule(x, y, couleur='bleue', rendu='mat'):
print(f"J'accroche une boule en ({x}, {y}) de couleur {couleur} et de rendu {rendu}.")
2. dans le répertoire exos/sous_paquet/ éditez un fichier nommé noel.py contenant :
— l’import de la fonction boule() depuis exos/sous_paquet2/deco.py
— la définition de la fonction boule_or() (cf. corrigé de l’exercice)
def boule_or(*args, **kwargs):
# seule instruction qui fait une hypothèse
# sur la signature de la fonction boule() :
kwargs['couleur'] = "or"
return boule(*args, **kwargs)
3. Décommentez la cellule ci-dessous, et exécutez-là pour vérifier que la fonction boule_or()
est bien importée.
boule_or(1, 2)
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[118], line 6
1 # Solution : décommentez les lignes suivantes pour positionner le corrigé
2
3 #!cp exos/sous_paquet/deco.py exos/sous_paquet2/
4 #!cp exos/sous_paquet2/noel.py exos/sous_paquet/
----> 6 from exos.sous_paquet.noel import boule_or
3.9. MODULES 79
8 boule_or(1, 2)
sys
— argv
— exit()
— path
Mais bien plus sur la doc officielle de la stdlib !
80 CHAPITRE 3. OPÉRATIONS, CONTRÔLE, FONCTIONS ET MODULES
Args:
n (int): nombre de répétitions
"""
return "rien" * n
help(nrien)
# ou dans ipython:
nrien?
nrien(n)
Retourne n fois 'rien'
Args:
n (int): nombre de répétitions
Plus d’information sur les Docstrings dans la documentation officielle et l’extension Napoleon pour
Sphinx.
nrien(3)
Out[120]: 'rienrienrien'
Ces annotations ne modifient pas l’exécution du code, mais elles présentent des avantages :
— elles indiquent au lecteur le type des arguments et de valeurs de retour,
— elles sont utilisées par les vérificateurs de code statique comme mypy et par Sphinx.
Cela permet d’éviter de nombreux bugs !
3.11. UTILISER LES ENVIRONNEMENTS DE DÉVELOPPEMENT INTÉGRÉS : 81
Exercice :
— placez dans une même fonction les portions de code exécutées plusieurs fois
— placez dans un même module les variables, fonctions et classes partagées entre plusieurs parties ou
programmes
— dans les projets importants, regrouper vos modules en packages
PEP 20
— pylint --py3k
— module de compatibilité : six
Plus d’informations sur le wiki officiel.
où codon1 et codon2 sont des codons synonymes : ils codent pour le même acide.
3.14.2 Consignes
1. Ecrire le code qui :
— ouvre le fichier code génétique
— lit son contenu avec le module csv pour générer le dictionnaire suivant :
2. Construire le dictionnaire inverse icode = {codon: letter} qui traduit un codon en acide aminé
représenté par sa lettre symbole.
3. Ecrire la fonction decode() qui admet comme argument la chaîne de caractères représentant une
séquence d’ARN et retourne la séquence d’acides aminés (appelée peptide) correspondante sous forme
de chaîne de caractères. En fonction de l’argument optionnel form, cette fonction retournera :
— soit une séquence de symboles (lettres)
— soit des abréviations d’acides aminés (séparées par des -).
In [129]: s = ''
help(s.join)
3.15. EXERCICES COMPLÉMENTAIRES 85
The string whose method is called is inserted in between each given string.
The result is returned as a new string.
4. Appliquer la fonction decode() à la chaîne de caractères représentant l’ARN contenue dans exos/arn.
txt.
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[133], line 21
16 def nom_propre(chaine: str) -> str:
17 # Votre code ici
18 pass
---> 21 assert majuscule("azERtyUI") == "AZERTYUI"
22 assert minuscule("azERtyUI") == "azertyui"
23 assert inverse_casse("azERtyUI") == "AZerTYui"
AssertionError:
3.15.2 Récursion
Les fonctions dites récursives sont des fonctions qui font appel à elles-même, en résolvant une partie plus
petite du problème à chaque appel, jusqu’à avoir un cas trivial à résoudre.
Par exemple, pour calculer la somme de tous les nombres de 0 jusqu’à x, on peut utiliser une fonction
récursive. Par exemple, pour 𝑥 = 10, on a :
10 9
— ∑𝑛=0 𝑛 = 10 + ∑𝑛=0 𝑛
9 8
— ∑𝑛=0 𝑛 = 9 + ∑𝑛=0 𝑛
— etc.
In [136]: print(sum_to(9))
45
La fonction mathématique factorielle est similaire, mais calcule le produit de tous les nombres de 1 jusqu’à
x.
120 362880
La fonction mathématique qui calcule la suite des nombres de Fibonacci, peut être décrite de la façon
suivante :
3.15. EXERCICES COMPLÉMENTAIRES 87
— fibo(0) = 0
— fibo(1) = 1
Et pour toutes les autres valeurs :
— fibo(x) = fibo(x - 1) + fibo(x - 2)
Exercice : écrivez une fonction récursive fibo(x) qui renvoie le x-ième nombre de la suite de
Fibonnaci.
print(fibo(9))
None
— Tableaux Numpy
— Création de tableaux
— Opérations basiques
— Indexation et slicing
— Algèbre linéaire
— Méthodes sur les tableaux
— Broadcasting de tableaux
4.1 Numpy
Le Python pur est peu performant pour le calcul. Les listes ne sont pas des objets efficaces pour représenter
les tableaux numériques de grande taille. Numpy a été créé à l’initiative de développeurs qui souhaitaient
combiner la souplesse du langage python et des outils de calcul algébrique performants.
Numpy se base sur :
— le ndarray : tableau multidimensionnel
— des objets dérivés comme les masked arrays et les matrices
— les ufuncs : opérations mathématiques optimisées pour les tableaux
— des méthodes pour réaliser des opération rapides sur les tableaux :
— manipulation des shapes
— tri
— entrées/sorties
89
90 CHAPITRE 4. UNE INTRODUCTION À NUMPY
— FFT
— algébre linéaire
— statistiques
— calcul aléatoire
— et bien plus !
Numpy permet de calculer à la Matlab en Python. Il est un élément de base de l’écosystème SciPy
1.26.4
In [2]: #np.nd<TAB>
In [3]: np.ndarray?
3.23 ms ± 62.9 �s per loop (mean ± std. dev. of 7 runs, 100 loops each)
25049.973798307085
20.9 �s ± 6.02 �s per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
25049.973798306608
4.4. CRÉATION DE TABLEAUX NUMPY 91
In [7]: print(a, b, c)
[0 1 2 3] [4 5 6 7] [[8 9 0 1]]
4.3.3 Propriétés
In [8]: a = np.array([1, 2, 3, 4, 5]) # On crée un tableau
Out[9]: numpy.ndarray
Out[10]: dtype('int64')
Out[11]: 8
Out[12]: (5,)
Out[13]: 5
Out[14]: 1
Out[15]: 40
— Toujours utiliser shape ou size pour les tableaux numpy plutôt que len
— len est réservé aux tableaux 1D
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
float64
[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]
int64
On dispose d’une panoplie de fonctions pour allouer des tableaux avec des valeurs constantes ou non
initialisées (empty) :
empty, empty_like, ones, ones_like, zeros, zeros_like, full, full_like
linspace et logspace
In [22]: # 5 éléments régulièrement espacés entre 1 et 4, 1 et 4 inclus
np.linspace(1, 4, 5)
Astuce : np.arange()
In [26]: # Solution
np.arange(100, 110)
Out[26]: array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109])
[-2. -1.8 -1.6 -1.4 -1.2 -1. -0.8 -0.6 -0.4 -0.2 0.
0.2 0.4 0.6 0.8 1. 1.2 1.4 1.6 1.8]
Astuce : np.linspace()
Astuce : np.logspace()
In [36]: np.loadtxt('test.out')
x: [0. 1. 2. 3. 4.]
y: [ 0. 10. 20. 30. 40.]
z: [ 0. 100. 200. 300. 400.]
[ 0 5 12 21]
[ 4 6 8 10]
In [40]: print(a**2)
4.6. INDEXATION ET SLICING 95
[0 1 4 9]
In [41]: print(5 * a)
print(5 + a)
[ 0 5 10 15]
[5 6 7 8]
[ 1. -1. 1. -1.]
[[0 1 2]
[3 4 5]
[6 7 8]]
5
4.6.2 Slicing
Pour les tableaux unidimensionnels, les règles de slicing sont les mêmes que pour les séquences. Pour
les tableaux multidimensionnels numpy, le slicing permet d’extraire des séquences dans n’importe quelle
direction.
In [46]: print(a)
print(a[2, :]) # Retourne la 3ème ligne
print(a[:, 1]) # Retourne la deuxième colonne
96 CHAPITRE 4. UNE INTRODUCTION À NUMPY
[[0 1 2]
[3 4 5]
[6 7 8]]
[6 7 8]
[1 4 7]
Attention : contrairement aux listes, le slicing de tableaux ne renvoie pas une copie mais constitue une
vue du tableau.
In [47]: b = a[:, 1]
b[0] = -1
print(a)
[[ 0 -1 2]
[ 3 4 5]
[ 6 7 8]]
a est aussi une vue du tableau np.arange(9) obtenue avec la méthode reshape() donc a et b sont deux
vues différentes du même tableau :
Out[48]: True
Si on veut réaliser une copie d’un tableau, il faut utiliser la fonction copy()
ici b n’est pas une vue mais une copie donc b.base vaut None et a n’est pas modifié.
In [50]: print(b.base)
b[0] = 200
print(a)
None
[[ 0 -1 2]
[ 3 4 5]
[ 6 7 8]]
4.6.3 Exercice
Approcher la dérivée de 𝑓(𝑥) = sin(𝑥) par la méthode des différences finies centrées :
𝜕𝑓 𝑓 (𝑥 + Δ𝑥 Δ𝑥
2 ) − 𝑓 (𝑥 − 2 )
≈
𝜕𝑥 Δ𝑥
Les valeurs seront calculées au milieu de deux abscisses discrètes successives.
— x représente les abscisses discrètes 𝑥𝑖 sur l’intervalle 𝑥𝑖 ∈ [0, 4𝜋] et dx le pas de discrétisation.
— y représente les valeurs de la fonction 𝑓(𝑥𝑖 ).
1. Calculer les valeurs de x_mil correspondant au milieu de l’intervale [𝑥𝑖 , 𝑥𝑖+1 ].
4.6. INDEXATION ET SLICING 97
2. Calculer les valeurs de dy_dx correspondant à la dérivée de y par différences finies centrées.
plt.title("Dérivée de sin(x)")
plt.xlabel(r"x")
plt.ylabel(r"$\frac{\partial f}{\partial x}$");
# Décommentez les lignes ci-dessous pour tracer la dérivée numérique dy_dx
# plt.plot(x_mil, np.cos(x_mil), label="cos(x)") # la dérivée analytique de sin() est cos()
# plt.plot(x_mil, dy_dx, 'rx', label="différences finies") # x_mil est le milieu de deux abscisses
plt.legend();
No artists with labels found to put in legend. Note that artists whose label start with an underscore a
[[2 0]
[0 4]]
[[5 4]
[3 4]]
[[5 4]
[3 4]]
[[5 4]
[3 4]]
Soit la matrice :
1 2
𝐴=( )
3 4
[[1. 2.]
[3. 4.]]
[[1. 3.]
[2. 4.]]
[[1. 3.]
[2. 4.]]
[[-2. 1. ]
[ 1.5 -0.5]]
[[1.00000000e+00 0.00000000e+00]
[1.11022302e-16 1.00000000e+00]]
5.0
[[1. 0.]
[0. 1.]]
[[-3.]
[ 4.]]
[[ True]
[ True]]
[[-1. 0.]
[ 0. -1.]]
EigResult(eigenvalues=array([0.+1.j, 0.-1.j]), eigenvectors=array([[0.70710678+0.j , 0.70710678-0
[0. -0.70710678j, 0. +0.70710678j]]))
In [67]: a + 1
100 CHAPITRE 4. UNE INTRODUCTION À NUMPY
[[1 1 1]
[1 1 1]
[1 1 1]]
In [69]: print(a)
[0 1 2]
In [70]: A + a
In [71]: a = np.arange(3)
print(a)
[0 1 2]
In [72]: b = np.arange(3).reshape(3, 1)
print(b)
[[0]
[1]
[2]]
In [73]: a + b
A =
[[1 1 1]
[1 1 1]]
a = [0 1 2]
A.shape = (2, 3)
a.shape = (3,)
In [75]: A + a
[[0]
[1]
[2]]
a.shape = (3, 1)
In [77]: b = np.arange(3)
print(b)
print(f"{b.shape = }")
[0 1 2]
b.shape = (3,)
In [78]: a + b
[[1 1]
[1 1]
[1 1]]
a.shape = (3, 2)
In [80]: b = np.arange(3)
print(b)
print(f"{b.shape = }")
[0 1 2]
b.shape = (3,)
In [81]: a + b
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[81], line 1
----> 1 a + b
ValueError: operands could not be broadcast together with shapes (3,2) (3,)
In [85]: X_centered.mean(0)
4.11 Références
— NumPy reference
— Numpy by Konrad Hinsen
— Cours de Pierre Navaro
— Python Datascience Handbook, par Jake VanderPlas
— Scipy Lecture notes
104 CHAPITRE 4. UNE INTRODUCTION À NUMPY
Chapitre 5
Microprojet
— Utiliser les modules de la bibliothèque standard pour récupérer des données via un service web.
— Manipuler les dictionnaires et les chaînes de caractères
— Utiliser la bibliothèque de tracés graphiques matplotlib
— Utiliser un IDE (Spyder)
— Exécuter un fichier script en gérant les arguments de la ligne de commande
5.1 Exercice
Exploiter les données du site https://www.prevision-meteo.ch pour tracer l’évolution horaire de la
température à Strasbourg aujourd’hui.
105
106 CHAPITRE 5. MICROPROJET
jsonfile_url = "https://www.prevision-meteo.ch/services/json/Strasbourg"
try:
f = urlopen(jsonfile_url, timeout=10) # open url
except Exception as e:
print(f"Erreur: {e}")
print("Le téléchargement a échoué : on lit une version locale.")
f = open("exos/Strasbourg.json")
In [3]: print(type(jsondict))
print(jsondict)
<class 'dict'>
{'city_info': {'name': 'Strasbourg', 'country': 'France', 'latitude': '48.5844421', 'longitude': '7.7558
'city_info'
'forecast_info'
'current_condition'
'fcst_day_0'
'fcst_day_1'
'fcst_day_2'
'fcst_day_3'
'fcst_day_4'
{'date': '28.01.2025', 'day_short': 'Mar.', 'day_long': 'Mardi', 'tmin': 5, 'tmax': 10, 'condition': 'Ec
'date'
'day_short'
'day_long'
'tmin'
'tmax'
'condition'
'condition_key'
'icon'
'icon_big'
'hourly_data'
Mardi 28.01.2025
'0H00'
'1H00'
'2H00'
'3H00'
'4H00'
'5H00'
'6H00'
'7H00'
'8H00'
'9H00'
'10H00'
'11H00'
'12H00'
'13H00'
'14H00'
'15H00'
'16H00'
'17H00'
'18H00'
'19H00'
'20H00'
'21H00'
'22H00'
'23H00'
'ICON'
'CONDITION'
'CONDITION_KEY'
'TMP2m'
'DPT2m'
'WNDCHILL2m'
'HUMIDEX'
'RH2m'
'PRMSL'
'APCPsfc'
'WNDSPD10m'
'WNDGUST10m'
'WNDDIR10m'
'WNDDIRCARD10'
'ISSNOW'
'HCDC'
'MCDC'
'LCDC'
'HGT0C'
'KINDEX'
'CAPE180_0'
'CIN180_0'
La clé qui nous intéresse est la chaîne 'TMP2m' qui correspond à la température à 2m du sol.
Sauver ces lignes de commandes dans le fichier today_stras.py en allant de l’exécution 1 au compteur
d’exécution courant indiqué dans la cellule de code ci-dessus In [XX]. Dans le cas présent :
Solution : exos/correction/meteo_json.py.
In [14]: # Pour tester votre script dans cette cellule, décommenter les lignes suivantes
# et redémarrer le noyau avant chaque modification :
Solution dans exos/correction/meteo_json_func.py. Dans cette correction, nous allons plus loin que
l’énoncé en découpant le script en quatre fonctions.
In [15]: # Correction
from exos.correction.meteo_json_func import main
main(2, city_name='Marseille')
110 CHAPITRE 5. MICROPROJET
interact(meteo.main,
day_key=list(range(5)),
city_name=["Marseille", "Paris", "Toulouse", "Strasbourg"]
);
import test_module
Dans ce cas, la variable interne __name__ vaut le nom du module (ici test_module).
— le code éxécuté lorsque le fichier est appelé directement comme un script depuis le terminal système :
python test_module.py
if __name__ == '__main__':
print("Je suis appelé comme programme principal")
main()
else:
# En mode module importé, on ne fait rien de plus
pass
Writing test_module.py
Le bloc qui appelle la fonction main() n’est pas exécuté. En revanche cette fonction est accessible à la
demande :
In [20]: test_module.main()
Cette fois-ci, la variable __name__ vaut test_module, c’est-à-dire le nom du module importé.
Plus d’information sur __name__ dans la doc officielle.
— Positionner des variables d’environnement qui peuvent être lues avec la fonction os.getenv() : le
risque est de dissocier la définition des paramètres de l’exécution du programme.
— lire un fichier d’entrée, par exemple avec configparser. C’est particulièrement utile lorsque les para-
mètres sont nombreux et variés et que l’on souhaite faciliter la reproductibilité des exécutions mais ça
demande d’éditer le fichier d’entrée à chaque changement de paramètre.
— interpréter les arguments de la ligne de commande : c’est la façon la plus souple d’exécuter un script
avec des paramètres variables.
Une façon très simple et très rapide créer une interface de ligne de commande (CLI en anglais) est
d’utiliser la bibliothèque fire développée par Google.
C’est une biblithèque externe : commençons par l’installer avec pip.
Note: you may need to restart the kernel to use updated packages.
À titre d’exemple, le fichier exos/correction/meteo_json_func.py appelle fire dans son bloc final :
if __name__ == '__main__':
import fire
fire.Fire(main)
NAME
meteo_json_func.py - Plot the time evolution of predicted temperature
SYNOPSIS
meteo_json_func.py <flags>
DESCRIPTION
Plot the time evolution of predicted temperature
FLAGS
-d, --day_key=DAY_KEY
Type: int
5.4. EXÉCUTION EN SCRIPT 113
Default: 0
-c, --city_name=CITY_NAME
Type: str
Default: 'strasbourg'
— les Series
— les Dataframes
— Des exemples de traitement de données publiques
115
116 CHAPITRE 6. UNE INTRODUCTION À PANDAS
6.2.1 Illustration
In [1]: import pandas as pd
import numpy as np
pd.set_option("display.max_rows", 8) # Pour limiter le nombre de lignes affichées
0 10
1 8
2 7
3 6
4 5
dtype: int64
0 4.0
1 3.0
2 2.0
3 1.0
4 0.0
dtype: float64
print(nee)
In [5]: for s in '.', '!', ',', '?', ':', '[', ']', 'ARTHUR', 'HEAD KNIGHT', 'PARTY':
nee = nee.replace(s, '')
['nee', 'nee', 'nee', 'nee', 'who', 'are', 'you', 'we', 'are', 'the', 'knights', 'who', 'say', 'nee', 'n
Notons que la série est ordonnée avec un index croissant (dans l’ordre alphabétique).
Out[9]: nee 16
who 8
are 6
you 7
..
of 4
and 6
a 6
shrubbery 4
Length: 13, dtype: int64
In [11]: words.plot(kind='bar');
6.2. LES PANDAS SERIES 119
Index(['nee', 'who', 'are', 'you', 'we', 'the', 'knights', 'say', 'not', 'of',
'and', 'a', 'shrubbery'],
dtype='object')
Out[12]: 16
Out[13]: and 6
a 6
shrubbery 4
dtype: int64
120 CHAPITRE 6. UNE INTRODUCTION À PANDAS
On télécharge et on nettoie
On commence par définir une fonction qui télécharge et extrait une archive zip.
6.3. LES PANDAS DATAFRAMES 121
arbres:
CUS_CUS_DEPN_ARBR.csv
Out[18]: Num point vert point vert NOM_USUEL point vert ADRESSE \
0 450.0 Rue du Houblon Houblon (rue du)
1 450.0 Rue du Houblon Houblon (rue du)
2 450.0 Rue du Houblon Houblon (rue du)
3 450.0 Rue du Houblon Houblon (rue du)
… … … …
79134 859.0 Krummerort Oberjaegerhof (route de l')
79135 859.0 Krummerort Oberjaegerhof (route de l')
79136 859.0 Krummerort Oberjaegerhof (route de l')
79137 859.0 Krummerort Oberjaegerhof (route de l')
… … …
79134 ACJF - Accompagnement de jardins familiaux 87652
79135 ACJF - Accompagnement de jardins familiaux 87653
79136 ACJF - Accompagnement de jardins familiaux 87654
79137 ACJF - Accompagnement de jardins familiaux 87655
In [24]: sorted(list(essences))[:5]
point vert ADRESSE point vert VILLE Point vert Quartier usuel \
2656 Hirschler (rue René) STRASBOURG CONSEIL-XV
2657 Hirschler (rue René) STRASBOURG CONSEIL-XV
9235 Wattwiller (39, rue de) STRASBOURG NEUDORF
9575 Rieth (51, rue du) STRASBOURG CRONENBOURG
… … … …
75935 Belges (quai des) STRASBOURG ESPLANADE
75940 Belges (quai des) STRASBOURG ESPLANADE
75941 Belges (quai des) STRASBOURG ESPLANADE
78276 Mélanie (rue) STRASBOURG ROBERTSAU
In [26]: ax = sapins['Libellé_Essence'].value_counts().plot(kind="barh");
ax.set_xlabel("nombre d'arbres");
On veut connaître la hauteur moyenne par essence pour chaque type Abies.
In [28]: download_unzip(r"https://data.strasbourg.eu/api/explore/v2.1/catalog/datasets/strasbourg-15-quartiers/expo
%ls -R quartiers
quartiers:
strasbourg-15-quartiers.cpg strasbourg-15-quartiers.shp
strasbourg-15-quartiers.dbf strasbourg-15-quartiers.shx
strasbourg-15-quartiers.prj
Note: you may need to restart the kernel to use updated packages.
geometry
0 POLYGON ((7.73488 48.56871, 7.73459 48.56614, …
1 POLYGON ((7.72644 48.57736, 7.72666 48.57717, …
2 POLYGON ((7.78101 48.57854, 7.78127 48.57923, …
3 POLYGON ((7.72644 48.57736, 7.72633 48.5773, 7…
.. …
11 POLYGON ((7.75002 48.57454, 7.74983 48.57463, …
12 POLYGON ((7.75904 48.56022, 7.75924 48.55992, …
13 POLYGON ((7.73488 48.56871, 7.73494 48.5695, 7…
14 POLYGON ((7.75513 48.59156, 7.75506 48.59133, …
Avec Folium, on commence par représenter ces données géographiques sur un fond de carte.
6.4. REPRÉSENTATION GÉOGRAPHIQUE 127
<folium.folium.Map at 0x7f49dc5a9290>
À l’emplacement de ces quartiers, on souhaite représenter une échelle de couleur en fonction de la densité
d’arbres.
On constate que les noms de quartiers sont différents de ceux du jeu de données sur les arbres.
set_quartiers = set(gdf_quartiers['libelle'])
set_arbres = set(arbres['Point vert Quartier usuel'])
print_set_data(set_quartiers)
print_set_data(set_arbres)
{'BOURSE-ESPLANADE-KRUTENAU',
'CENTRE',
'CRONENBOURG',
'ELSAU',
'HAUTEPIERRE',
'KOENIGSHOFFEN',
'MEINAU',
'MONTAGNE-VERTE',
'NEUDORF',
'NEUHOF1',
'NEUHOF2',
'ORANGERIE-CONSEIL DES XV',
'PORT DU RHIN',
'ROBERTSAU',
'TRIBUNAL-GARE-PORTE DE SCHIRMECK'} -> 15
{'BOURSE',
'CENTRE',
'CONSEIL-XV',
'CRONENBOURG',
'ELSAU',
'ESPLANADE',
'GARE',
'HAUTEPIERRE',
'KOENIGSHOFFEN',
128 CHAPITRE 6. UNE INTRODUCTION À PANDAS
'KRUTENAU',
'MEINAU',
'MONTAGNE VERTE',
'MUSAU',
'NEUDORF',
'NEUHOF',
'ORANGERIE',
'PLAINE DES BOUCHERS',
'POLYGONE',
'PORT DU RHIN',
'PORTE DE SCHIRMECK',
'ROBERTSAU',
'STOCKFELD',
'TRIBUNAL',
'WACKEN'} -> 24
{'CENTRE',
'CRONENBOURG',
'ELSAU',
'HAUTEPIERRE',
'KOENIGSHOFFEN',
'MEINAU',
'NEUDORF',
'PORT DU RHIN',
'ROBERTSAU'} -> 9
{'BOURSE',
'CONSEIL-XV',
'ESPLANADE',
'GARE',
'KRUTENAU',
'MONTAGNE VERTE',
'MUSAU',
'NEUHOF',
'ORANGERIE',
'PLAINE DES BOUCHERS',
'POLYGONE',
'PORTE DE SCHIRMECK',
'STOCKFELD',
'TRIBUNAL',
'WACKEN'} -> 15
Afin d’obtenir de faire correspondre parfaitement les noms des deux jeux de données, on convertit les
noms dans le Dataframe arbres en supposant les correspondances ci-dessous.
6.4. REPRÉSENTATION GÉOGRAPHIQUE 129
In [35]: convertion_dict = {
'BOURSE': 'BOURSE-ESPLANADE-KRUTENAU',
'CONSEIL-XV': 'ORANGERIE-CONSEIL DES XV',
'ESPLANADE': 'BOURSE-ESPLANADE-KRUTENAU',
'GARE': 'TRIBUNAL-GARE-PORTE DE SCHIRMECK',
'KRUTENAU': 'BOURSE-ESPLANADE-KRUTENAU',
'MONTAGNE VERTE': 'MONTAGNE-VERTE',
'MUSAU': 'NEUDORF',
'NEUHOF': 'NEUHOF1',
'ORANGERIE': 'ORANGERIE-CONSEIL DES XV',
'PLAINE DES BOUCHERS': 'MEINAU',
'POLYGONE': 'NEUHOF1',
'PORTE DE SCHIRMECK': 'TRIBUNAL-GARE-PORTE DE SCHIRMECK',
'STOCKFELD': 'NEUHOF2',
'TRIBUNAL': 'TRIBUNAL-GARE-PORTE DE SCHIRMECK',
'WACKEN': 'ROBERTSAU'
}
for k, v in convertion_dict.items():
arbres['Point vert Quartier usuel'] = \
arbres['Point vert Quartier usuel'].replace(to_replace=k, value=v)
arbres
Out[35]: Num point vert point vert NOM_USUEL point vert ADRESSE \
0 450.0 Rue du Houblon Houblon (rue du)
1 450.0 Rue du Houblon Houblon (rue du)
2 450.0 Rue du Houblon Houblon (rue du)
3 450.0 Rue du Houblon Houblon (rue du)
… … … …
79134 859.0 Krummerort Oberjaegerhof (route de l')
79135 859.0 Krummerort Oberjaegerhof (route de l')
79136 859.0 Krummerort Oberjaegerhof (route de l')
79137 859.0 Krummerort Oberjaegerhof (route de l')
On vérifie que l’ensemble des quartiers est le même pour les deux Dataframes quartiers et arbres.
Out[36]: True
In [38]: arbres_quartiers.plot(kind='barh');
On construit une nouvelle Series correspondant à l’aire de chaque quartier en 𝑚2 . Pour que le calcul
des aires soit fiables, les données de gdf_quartier doivent être projetées. Pour la France métropolitaine, on
utilise la projection EPSG :2154, c’est-à-dire Lambert 93.
libelle
ELSAU 1.895918e+06
MONTAGNE-VERTE 2.103470e+06
ORANGERIE-CONSEIL DES XV 2.857609e+06
KOENIGSHOFFEN 2.717087e+06
…
BOURSE-ESPLANADE-KRUTENAU 1.820240e+06
NEUHOF1 3.947680e+06
MEINAU 4.777885e+06
TRIBUNAL-GARE-PORTE DE SCHIRMECK 3.359467e+06
Length: 15, dtype: float64
On trace une carte colorée par la densité d’arbres avec l’objet Choropleth.
In [41]: folium.Choropleth(geo_data=gdf_quartiers,
data=densite,
key_on='feature.properties.libelle',
fill_color='YlGn',
fill_opacity=0.5,
line_opacity=0.2,
legend_name=r"Nombre d\'arbres par hectare").add_to(stras_map)
stras_map.save('stras_tree.html')
display(stras_map)
<folium.folium.Map at 0x7f49dc5a9290>
6.4.1 Exercice
Ecrire la fonction plot_essence() qui prend en argument une essence d’arbres et qui trace le nombre
d’arbres correspondant par quartier en utilisant choropleth.
plot_essence("Acer")
interact(plot_essence, essence=sorted(genres));
voila exos/stras_arbres.ipynb
6.5 Références
— La documentation officielle
— Le cours de Pierre Navaro
— Le cours de Jake Vanderplas
— Des sites personnels de développeurs :
— http ://wesmckinney.com/
— https ://matthewrocklin.com/