Structures avancées et matrices
Au-delà des listes
Section intitulée « Au-delà des listes »Les listes sont polyvalentes, mais certains problèmes demandent des structures mieux adaptées.
| Problème | Avec une liste | Inconvénient |
|---|---|---|
| Éliminer les doublons d’une collection | Parcourir et vérifier not in à chaque ajout | Lent, laborieux |
| Associer un nom à une note ou créer un enregistrement | Deux listes parallèles noms[i] / notes[i] | Fragile, facile à désynchroniser |
Python offre des structures spécialisées pour chacun de ces cas.
Les ensembles
Section intitulée « Les ensembles »Un ensemble (set) est une collection non ordonnée d’éléments uniques. Pas de doublons, pas d’indice.
Créer un ensemble
Section intitulée « Créer un ensemble »Avec des accolades
Section intitulée « Avec des accolades »couleurs = {"rouge", "vert", "bleu"}
print(couleurs)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »{'rouge', 'bleu', 'vert'}À partir d’une liste (élimine les doublons)
Section intitulée « À partir d’une liste (élimine les doublons) »nombres = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]uniques = set(nombres)print(uniques)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »{1, 2, 3, 4, 5, 6, 9}Opérations sur les ensembles
Section intitulée « Opérations sur les ensembles »fruits = {"pomme", "banane", "cerise"}
# Ajouterfruits.add("mangue")print(fruits)
# Retirer (sans erreur si absent)fruits.discard("banane")print(fruits)
# Appartenanceprint("cerise" in fruits)print("kiwi" in fruits)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »{'pomme', 'banane', 'cerise', 'mangue'}{'pomme', 'cerise', 'mangue'}TrueFalseOpérations mathématiques
Section intitulée « Opérations mathématiques »Les ensembles supportent les opérations classiques de la théorie des ensembles.
a = {1, 2, 3, 4, 5}b = {4, 5, 6, 7, 8}
print("Union :", a | b)print("Intersection :", a & b)print("Différence :", a - b)print("Différence symétrique :", a ^ b)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »Union : {1, 2, 3, 4, 5, 6, 7, 8}Intersection : {4, 5}Différence : {1, 2, 3}Différence symétrique : {1, 2, 3, 6, 7, 8}| Opération | Symbole | Description |
|---|---|---|
| Union | a | b | Tous les éléments de a et b |
| Intersection | a & b | Éléments communs à a et b |
| Différence | a - b | Éléments dans a mais pas dans b |
| Différence symétrique | a ^ b | Éléments dans a ou b, mais pas les deux |
Les dictionnaires
Section intitulée « Les dictionnaires »Un dictionnaire (dict) associe des clés à des valeurs.
Créer un dictionnaire
Section intitulée « Créer un dictionnaire »# Avec la syntaxe clé: valeuretudiant = { "nom": "Alice", "age": 20, "note": 87.5}
print(etudiant)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »{'nom': 'Alice', 'age': 20, 'note': 87.5}Au lieu de chercher par position (comme dans une liste), on cherche par clé.
Accéder aux valeurs
Section intitulée « Accéder aux valeurs »etudiant = {"nom": "Alice", "age": 20, "note": 87.5}
print(etudiant["nom"])print(etudiant["age"])Résultat de l’exécution
Section intitulée « Résultat de l’exécution »Alice20Modifier et ajouter
Section intitulée « Modifier et ajouter »Modifier une valeur existante
Section intitulée « Modifier une valeur existante »etudiant = {"nom": "Alice", "age": 20, "note": 87.5}etudiant["note"] = 92.0
print(etudiant)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »{'nom': 'Alice', 'age': 20, 'note': 92.0}Ajouter une nouvelle clé
Section intitulée « Ajouter une nouvelle clé »etudiant = {"nom": "Alice", "age": 20, "note": 87.5}
etudiant["groupe"] = "A"
print(etudiant)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »{'nom': 'Alice', 'age': 20, 'note': 87.5, 'groupe': 'A'}Parcourir un dictionnaire
Section intitulée « Parcourir un dictionnaire »notes = {"Alice": 88, "Bob": 72, "Charlie": 95}
# Parcourir les clésfor nom in notes: print(nom)
# Parcourir les valeursfor note in notes.values(): print(note)
# Parcourir les paires clé-valeurfor nom, note in notes.items(): print(nom, ":", note)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »AliceBobCharlie887295Alice : 88Bob : 72Charlie : 95Méthodes utiles
Section intitulée « Méthodes utiles »| Méthode | Description |
|---|---|
d[cle] | Accéder à la valeur (erreur si absente) |
d.get(cle, defaut) | Accéder avec valeur par défaut |
d[cle] = valeur | Ajouter ou modifier |
del d[cle] | Supprimer une paire |
cle in d | Vérifier si une clé existe |
d.keys() | Toutes les clés |
d.values() | Toutes les valeurs |
d.items() | Toutes les paires (clé, valeur) |
len(d) | Nombre de paires |
Listes parallèles vs dictionnaire
Section intitulée « Listes parallèles vs dictionnaire »noms = ["Alice", "Bob", "Charlie"]notes = [88, 72, 95]
# Trouver la note de Bobfor i in range(len(noms)): if noms[i] == "Bob": print(notes[i])notes = {"Alice": 88, "Bob": 72, "Charlie": 95}
# Trouver la note de Bobprint(notes["Bob"])Le dictionnaire est plus lisible, plus rapide, et impossible à désynchroniser.
Vers les données tabulaires
Section intitulée « Vers les données tabulaires »Les ensembles et dictionnaires organisent des données par unicité ou par clé. Cependant, on travaille souvent avec des données tabulaires : des lignes et des colonnes.
Imagine un laboratoire qui mesure la température de l’eau à 3 stations pendant 5 jours :
| Lundi | Mardi | Mercredi | Jeudi | Vendredi | |
|---|---|---|---|---|---|
| Station A | 12.3 | 12.8 | 13.1 | 12.9 | 13.4 |
| Station B | 14.1 | 14.5 | 14.2 | 14.8 | 15.0 |
| Station C | 11.7 | 11.9 | 12.0 | 12.3 | 12.1 |
Ce tableau a 3 lignes (stations) et 5 colonnes (jours). Pour le représenter en Python, on a besoin de listes imbriquées.
Listes imbriquées et matrices
Section intitulée « Listes imbriquées et matrices »Une liste imbriquée est une liste dont les éléments sont eux-mêmes des listes. Chaque sous-liste représente une ligne du tableau.
temperatures = [ [12.3, 12.8, 13.1, 12.9, 13.4], [14.1, 14.5, 14.2, 14.8, 15.0], [11.7, 11.9, 12.0, 12.3, 12.1]]En mathématiques, quand une liste imbriquée contient des nombres et que toutes les sous-listes ont la même longueur, on parle de matrice.
C’est une matrice (3 lignes, 5 colonnes).
Initialisation
Section intitulée « Initialisation »Valeurs connues
Section intitulée « Valeurs connues »matrice = [ [1, 2, 3], [4, 5, 6], [7, 8, 9]]Matrice de zéros
Section intitulée « Matrice de zéros »lignes = 3colonnes = 4
matrice = []for i in range(lignes): ligne = [] for j in range(colonnes): ligne.append(0) matrice.append(ligne)
print(matrice)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]Matrice identité
Section intitulée « Matrice identité »La matrice identité a des 1 sur la diagonale et des 0 partout ailleurs.
taille = 4identite = []
for i in range(taille): ligne = [] for j in range(taille): if i == j: ligne.append(1) else: ligne.append(0) identite.append(ligne)
for ligne in identite: print(ligne)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »[1, 0, 0, 0][0, 1, 0, 0][0, 0, 1, 0][0, 0, 0, 1]Adressage
Section intitulée « Adressage »On accède à un élément par matrice[ligne][colonne].
temperatures = [ [12.3, 12.8, 13.1, 12.9, 13.4], [14.1, 14.5, 14.2, 14.8, 15.0], [11.7, 11.9, 12.0, 12.3, 12.1]]
# Station A, mercredi (ligne 0, colonne 2)print(temperatures[0][2])
# Station C, vendredi (ligne 2, colonne 4)print(temperatures[2][4])
# Modifier : Station B, jeuditemperatures[1][3] = 14.6print(temperatures[1][3])Résultat de l’exécution
Section intitulée « Résultat de l’exécution »13.112.114.6 colonne 0 colonne 1 colonne 2 colonne 3 colonne 4 ┌──────────┬──────────┬──────────┬──────────┬──────────┐ ligne 0 │ 12.3 │ 12.8 │ 13.1 │ 12.9 │ 13.4 │ ├──────────┼──────────┼──────────┼──────────┼──────────┤ ligne 1 │ 14.1 │ 14.5 │ 14.2 │ 14.8 │ 15.0 │ ├──────────┼──────────┼──────────┼──────────┼──────────┤ ligne 2 │ 11.7 │ 11.9 │ 12.0 │ 12.3 │ 12.1 │ └──────────┴──────────┴──────────┴──────────┴──────────┘Dimensions
Section intitulée « Dimensions »temperatures = [ [12.3, 12.8, 13.1, 12.9, 13.4], [14.1, 14.5, 14.2, 14.8, 15.0], [11.7, 11.9, 12.0, 12.3, 12.1]]
nb_lignes = len(temperatures)nb_colonnes = len(temperatures[0])
print("Lignes :", nb_lignes)print("Colonnes :", nb_colonnes)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »Lignes : 3Colonnes : 5len(matrice) donne le nombre de lignes. len(matrice[0]) donne le nombre de colonnes (en supposant que toutes les lignes ont la même longueur).
Traversée
Section intitulée « Traversée »Parcourir ligne par ligne
Section intitulée « Parcourir ligne par ligne »matrice = [ [1, 2, 3], [4, 5, 6], [7, 8, 9]]
for ligne in matrice: print(ligne)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »[1, 2, 3][4, 5, 6][7, 8, 9]Parcourir élément par élément
Section intitulée « Parcourir élément par élément »matrice = [ [1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i in range(len(matrice)): for j in range(len(matrice[i])): print("matrice[", i, "][", j, "] = ", matrice[i][j])Résultat de l’exécution
Section intitulée « Résultat de l’exécution »matrice[0][0] = 1matrice[0][1] = 2matrice[0][2] = 3matrice[1][0] = 4matrice[1][1] = 5matrice[1][2] = 6matrice[2][0] = 7matrice[2][1] = 8matrice[2][2] = 9Somme par ligne et par colonne
Section intitulée « Somme par ligne et par colonne »Reprenons les températures pour calculer la moyenne par station (par ligne) et la moyenne par jour (par colonne).
temperatures = [ [12.3, 12.8, 13.1, 12.9, 13.4], [14.1, 14.5, 14.2, 14.8, 15.0], [11.7, 11.9, 12.0, 12.3, 12.1]]
stations = ["Station A", "Station B", "Station C"]jours = ["Lun", "Mar", "Mer", "Jeu", "Ven"]
# Moyenne par station (par ligne)print("=== Moyenne par station ===")for i in range(len(temperatures)): moyenne = sum(temperatures[i]) / len(temperatures[i]) print(format("{} : {:.1f} °C", stations[i], moyenne))
# Moyenne par jour (par colonne)print()print("=== Moyenne par jour ===")for j in range(len(temperatures[0])): somme = 0 for i in range(len(temperatures)): somme = somme + temperatures[i][j] moyenne = somme / len(temperatures) print(format("{} : {:.1f} °C", jours[j], moyenne))Résultat de l’exécution
Section intitulée « Résultat de l’exécution »=== Moyenne par station ===Station A : 12.9 °CStation B : 14.5 °CStation C : 12.0 °C
=== Moyenne par jour ===Lun : 12.7 °CMar : 13.1 °CMer : 13.1 °CJeu : 13.3 °CVen : 13.5 °COpérations mathématiques sur matrices
Section intitulée « Opérations mathématiques sur matrices »Addition de matrices
Section intitulée « Addition de matrices »Deux matrices de même dimension s’additionnent élément par élément.
Multiplication par un scalaire
Section intitulée « Multiplication par un scalaire »Chaque élément est multiplié par le même nombre.
Transposée
Section intitulée « Transposée »La transposée échange les lignes et les colonnes : l’élément [i][j] devient [j][i].
Multiplication matricielle
Section intitulée « Multiplication matricielle »Le produit de deux matrices () et () donne une matrice () où chaque élément est :
Introduction à NumPy
Section intitulée « Introduction à NumPy »Les opérations matricielles avec des listes imbriquées sont verbeuses et lentes. Additionner deux matrices de 1000×1000 demande un million d’itérations dans une boucle Python.
NumPy (Numerical Python) est la bibliothèque de calcul scientifique de référence en Python. Elle fournit un type de données optimisé — le tableau NumPy (ndarray) — et des opérations vectorisées qui s’exécutent en C, pas en Python.
Installation
Section intitulée « Installation »NumPy n’est pas inclus dans Python par défaut. Il faut l’installer (une seule fois) :
pip install numpyCréer un tableau NumPy
Section intitulée « Créer un tableau NumPy »import numpy as np
# À partir d'une listenotes = np.array([85, 92, 78, 95, 88])print(notes)print(type(notes))
# À partir d'une liste imbriquée → matricematrice = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])print(matrice)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »[85 92 78 95 88]<class 'numpy.ndarray'>[[1 2 3] [4 5 6] [7 8 9]]Tableaux spéciaux
Section intitulée « Tableaux spéciaux »import numpy as np
print(np.zeros((2, 3))) # Matrice 2x3 de zérosprint()print(np.ones((3, 2))) # Matrice 3x2 de unsprint()print(np.eye(4)) # Matrice identité 4x4print()print(np.arange(0, 10, 2)) # Comme range() mais retourne un tableauprint()print(np.linspace(0, 1, 5)) # 5 valeurs espacées régulièrement entre 0 et 1Résultat de l’exécution
Section intitulée « Résultat de l’exécution »[[0. 0. 0.] [0. 0. 0.]]
[[1. 1.] [1. 1.] [1. 1.]]
[[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]]
[0 2 4 6 8]
[0. 0.25 0.5 0.75 1. ]Propriétés d’un tableau
Section intitulée « Propriétés d’un tableau »import numpy as np
matrice = np.array([[1, 2, 3], [4, 5, 6]])
print("Forme :", matrice.shape)print("Type :", matrice.dtype)print("Taille :", matrice.size)print("Dimensions :", matrice.ndim)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »Forme : (2, 3)Type : int64Taille : 6Dimensions : 2Opérations vectorisées
Section intitulée « Opérations vectorisées »C’est la raison d’utiliser NumPy. Les opérations s’appliquent à tous les éléments en une seule instruction, sans boucle.
a = [1, 2, 3]b = [4, 5, 6]
# Addition élément par élémentresultat = []for i in range(len(a)): resultat.append(a[i] + b[i])print(resultat)import numpy as np
a = np.array([1, 2, 3])b = np.array([4, 5, 6])
resultat = a + bprint(resultat)Les deux affichent [5, 7, 9], mais NumPy le fait sans boucle et beaucoup plus vite.
import numpy as np
a = np.array([10, 20, 30, 40])
print("+ 5 :", a + 5)print("* 2 :", a * 2)print("** 2 :", a ** 2)print("/ 10 :", a / 10)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »+ 5 : [15 25 35 45]* 2 : [20 40 60 80]** 2 : [100 400 900 1600]/ 10 : [1. 2. 3. 4.]Opérations matricielles avec NumPy
Section intitulée « Opérations matricielles avec NumPy »Les opérations qui demandaient des boucles imbriquées deviennent triviales.
import numpy as np
a = np.array([[1, 2], [3, 4]])b = np.array([[5, 6], [7, 8]])
print("Addition :")print(a + b)print()
print("Scalaire :")print(a * 3)print()
print("Transposée :")print(a.T)print()
print("Produit matriciel :")print(a @ b)Résultat de l’exécution
Section intitulée « Résultat de l’exécution »Addition :[[ 6 8] [10 12]]
Scalaire :[[ 3 6] [ 9 12]]
Transposée :[[1 3] [2 4]]
Produit matriciel :[[19 22] [43 50]]| Opération | Listes imbriquées | NumPy |
|---|---|---|
| Addition | Double boucle + append | a + b |
| Scalaire | Double boucle + append | a * 3 |
| Transposée | Double boucle inversée | a.T |
| Produit matriciel | Triple boucle | a @ b |
Indexation NumPy
Section intitulée « Indexation NumPy »NumPy offre une syntaxe d’indexation plus concise que les listes imbriquées.
import numpy as np
temperatures = np.array([ [12.3, 12.8, 13.1, 12.9, 13.4], [14.1, 14.5, 14.2, 14.8, 15.0], [11.7, 11.9, 12.0, 12.3, 12.1]])
# Un élément : ligne 0, colonne 2print(temperatures[0, 2])
# Une ligne complète : station Bprint(temperatures[1, :])
# Une colonne complète : mercrediprint(temperatures[:, 2])
# Sous-matrice : stations A et B, lundi à mercrediprint(temperatures[0:2, 0:3])Résultat de l’exécution
Section intitulée « Résultat de l’exécution »13.1[14.1 14.5 14.2 14.8 15.0][13.1 14.2 12.0][[12.3 12.8 13.1] [14.1 14.5 14.2]]| Structure | Utilité principale | Syntaxe de création |
|---|---|---|
Ensemble (set) | Collection sans doublons, tests d’appartenance rapides | {1, 2, 3} ou set(liste) |
Dictionnaire (dict) | Associer des clés à des valeurs | {"clé": valeur} |
| Liste imbriquée | Tableaux 2D, grilles, matrices | [[1, 2], [3, 4]] |
Tableau NumPy (ndarray) | Calcul numérique rapide et concis | np.array([[1, 2], [3, 4]]) |