Construction par compréhension
I. Premiers tableaux en compréhension⚓︎
Un tableau peut s'initialiser avec des éléments par défaut de plusieurs manières.
En voici deux :
Le langage Python permet une autre manière pour créer des tableaux : il s'agit de la construction par compréhension.
Cela permet de créer des tableaux que nous n'aurions pas su créer avec la méthode précédente. Par exemple, comment créer le tableaux contenant les 1000 premiers carrés : 1, 4, 9, 16, 25 etc ? Nous allons étudier comment procéder dans ce cours.
Le code suivant permet également de créer un tableau de 4 éléments initialisés à 0. C'est une création de tableau par compréhension. on dit aussi que le tableau est écrit en compréhension
De la même façon, la boucle suivante : peut s'écrire :Question
-
tableau = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
-
tableau = [i, i, i, i, i, i, i, i, i, i]
-
tableau = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-
tableau = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
- La valeur 15 est exclue.
- i prend les valeurs de l'intervalle.
- La valeur n'est pas contante.
- i prend tour à tour les valeurs de 5 jusqu'à 14.
Question
Ecrire en compréhension la liste [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
qui contient 20 fois l'entier 5.
Question
Compléter le script ci-dessous :
On peut aussi utiliser des chaînes de caractères :
Testez
Exécuter le script ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Question
Ecrire en compréhension : ['NSI-1', 'NSI-2', 'NSI-3', 'NSI-4', 'NSI-5', 'NSI-6', 'NSI-7', 'NSI-8', 'NSI-9', 'NSI-10']
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Quelques exemples⚓︎
Question
Compléter ci dessous le script : Ecrire en compréhension lst3
qui donne la liste de la somme des éléments de [2, 3, 1, 5] et de [4, 1, 7, 0].
On doit obtenir : [6, 4, 8, 5]
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Question
Répondre sur papier.
Donner les listes lst1, lst2, lst4, lst6 et lst7
II. Utilisation plus élaborée des tableaux en compréhension⚓︎
Grâce à la construction par compréhension, il est possible d'appliquer un traitement (opération, fonction...) à chaque élément d'un tableau.
Testez
Exécuter le script ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Question
-
double = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
double = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
-
double = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
-
double = [4, 8, 12, 16]
- Un traitement est appliqué aux valeurs prises par i.
- Le mauvais traitement est appliqué.
- le tableau est composé du double de chaque valeur de l'intervalle [0,9]
- Le tableau double doit contenir autant d'éléments que le tableau d'origine.
III. Appliquer un filtre⚓︎
La construction par compréhension permet d'appliquer un filtre à une structure de données de départ, afin de ne garder que certains éléments. On utilise pour cela une condition précédée du mot-clé if
.
On peut ainsi créer un tableau qui ne conserve que les nombres pairs d'un tableau initial.
>>> tableau = [0, 1, 6, 5, 4, 11, 12, 23, 26]
>>> pairs = [p for p in tableau if p%2 == 0]
>>> pairs
[0, 6, 4, 12, 26]
Question
-
nouveau_tableau = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
-
nouveau_tableau = [5, 6, 7, 8, 9]
-
nouveau_tableau = [9, 8, 7, 6, 5]
-
nouveau_tableau = [10, 11, 12, 13, 14]
- La condition entraine la sélection de certaines valeurs.
- on sélectionne tous les éléments du tableau inférieurs à 10.
- Les éléments conservent l'ordre dans lequel il se trouvent dans le tableau initial.
- La condition indique les éléments qui sont conservés.
Question
Créer en compréhension la liste des carrés des nombres de la liste nombres
qui sont négatifs.
Question
Compléter le script ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Solution
# un tableau positifs en compréhension qui contient
# les nombres réels positifs du tableau nombres
nombres = [1, 0, -2, 9, -5, 4, -7, 5, -8]
positifs = [k for k in nombres if k > 0]
# un tableau voyelle_phrase en compréhension qui ne contient que les voyelles
# contenues dans la chaine de caractère phrase
phrase = "je ne suis pas sans voix !"
VOYELLES = "aeiouy"
voyelle_phrase = [caractere for caractere in phrase if caractere in VOYELLES]
IV. Les tableaux de tableaux⚓︎
Pour construire un tableau de tableaux de même longueurs, on peut utiliser des compréhensions imbriquées.
Dans les exemples qui suivent nous appelerons matrice
notre tableau de tableaux.
>>> matrice = [[k for k in range(4)] for j in range(3)]
>>> matrice
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
Pour bien visualiser le tableau matrice
que nous venons de créer, nous pouvons l'écrire de la façon suivante :
matrice
correspond donc à une "ligne".
On peut considérer que matrice
a quatre "colonnes". Par exemple la première colonne (de rang 0) est [0, 0, 0]
, et la dernière est [3, 3, 3]
.
💡 Il est possible d'extraire une ligne de matrice
.
💡 Il est possible d'extraire une colonne de matrice
.
QCM 1
-
matrice = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
-
matrice = [[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
-
matrice = [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
-
matrice = [0, 1, 2, 3]
- La valeur j est constante pour chaque ligne.
- La valeur j prend la valeur 0 pour la première ligne, puis 1, etc.
- La valeur j est constante pour chaque ligne.
- Les constructions imbriquées engendrent un tableau de tableaux.
Puzzle 1
Créer en compréhension la matrice [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
À vous de jouer 1
Compléter le script ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Solution
# un tableau matrice_carre_10 en compréhension, matrice 10x10
# dont chaque ligne contient les entiers de 1 à 10.
matrice_carre_10 = [[k for k in range(1, 11)] for j in range(10)]
# un tableau ligne_5 en compréhension qui contient la colonne 5 (située à l'indice 4)
# de la matrice matrice_carre_10
colonne_5 = [ligne[4] for ligne in matrice_carre_10]
# un tableau diagonale en compréhension qui contient les éléments situés
# à la 1ère colonne de la 1ère ligne,
# à la 2ème colonne de la 2ème ligne ... de la matrice carrée matrice_carre_10
diagonale = [matrice_carre_10[i][i] for i in range(len(matrice_carre_10))]
À vous de jouer 2
Compléter la fonction donne_colonne
qui prend en paramètres une matrice matrice
, un entier colonne
et renvoie la liste des éléments de la colonne colonne
.
Nous avons déjà réalisé cet exercice dans le chapitre : listes de listes. Vous devez ici absolument utiliser une liste en compréhension.
Par exemple :
>>> m = [[1, 3, 4],
[5, 6, 8],
[2, 1, 3],
[7, 8, 15]]
>>> donne_colonne(m, 0)
[1, 5, 2, 7]
>>> donne_colonne(m, 2)
[4, 8, 3, 15]
>>>
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À vous de jouer 3
Compléter le script ci-dessous :
👉 Vous pouvez tester les ###
en haut à droite de la fenêtre.
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Solution
def get_diag_2(lst) -> list :
"""
Entrée : lst : une liste de listes de mêmes longueurs
Sortie : diag_2 : une liste dont les éléments sont les éléments de
la 2eme diagonale (de en bas à gauche à en haut droite)
>>> m = [ [1, 3, 4],
[5 ,6 ,8],
[2, 1, 3] ]
>>> get_diag_2(m)
[4, 6, 2]
"""
indice_max = len(lst) - 1
return [lst[i][indice_max-i] for i in range(len(lst))]
V. Exercices⚓︎
1. Exercices variés⚓︎
Nombres pairs
Ecrire en compréhension le liste des cinq premiers entiers pairs.
À vous de jouer 1 : Table de multiplication
Ecrire La liste des entiers de la table de multiplication de 9 : [9, 18, ..., 90]
À vous de jouer 2 : les puissances de 2
Ecrire en compréhension la liste suivante des tuples donnant les puissances de 2 :
[(0, 1), (1, 2), (2, 4), (3, 8), (4, 16), (5, 32), (6, 64), (7, 128)]
Une liste dans une liste en compréhension
Tester :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Des filtres
Tester :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À vous de jouer 3
Ecrire la liste des entiers inférieurs à 100 qui sont à la fois multiples de 3 et de 5.
À vous de jouer 4
On donne une liste de coordonnées de points : points
.
Compléter le script pour afficher la liste des coordonnées des points se trouvant sur
la droite d'équation \(y=2x+1\)
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À vous de jouer 5
On donne une liste d'élèves d'un groupe : lst_eleves
. Compléter le script pour
écrire une liste en compréhension qui contient la liste des élèves dont le nom commence par A ou B.
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À vous de jouer 6
On donne une liste de séquences ADN. Ecrire une liste extraite de la précédente, avec seulement les séquances contenant "AAT"
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À vous de jouer 7 : simuler un jeu
💡 Encore plus fort : utilisation du booléen.
1. Tester ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À quoi sert ma_liste_2
?
Solution
Cette liste permet de simuler 20 lancers de dés, et de noter pour chacun True ou False suivant que le dé est tombé sur 6 ou non.
2. On va simuler le jeu suivant :
On tire au hasard un numéro parmi 1, 2, 3, 4, 5, 6, 7, 8, 9 et 10.
Si le numéro obtenu est strictement inférieur à 7 (parmi 1, 2, 3, 4, 5, 6), on gagne un bonbon. Sinon, on perd.
On veut créer la liste parties
de 50 résultats obtenus, si l'on joue 50 fois.
On obtient le booléen True
lorsque l'on gagne, et le booléen False
lorsque l'on perd. La liste parties
est donc composée de ces 50 booléens.
A-t-on plus de chance de gagner ou de perdre ?
Compléter ci-dessous pour qu'il s'affiche le nombre de True
et le nombre de False
de la liste.
Exécuter votre code plusieurs fois pour observer les résultats obtenus.
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Solution
3. Dans la question 2. nous avons simulé 50 parties. Nous voulons maintenant pouvoir simuler un nombre quelconque de parties.
Compléter la fonction simulation
qui prend en paramètre un entier n
et renvoie un tuple dont le premier élément est le
nombre de True
et le second le nombre de False
obtenus pour n
parties. Il ne faut pas faire afficher les listes obtenues.
Compléter également le script pour qu'il s'affiche le nombre de True
et de False
respectivement pour 100 puis 1000 parties.
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Solution
from random import randint
def simulation(n):
"""
n est le nombre de parties que l'on va simuler
"""
parties = [randint(1, 10) < 7 for i in range(n)]
nbre_T = 0
nbre_F = 0
for elt in parties:
if elt == True:
nbre_T = nbre_T + 1
else:
nbre_F = nbre_F + 1
return (nbre_T, nbre_F)
(nbre_T_100, nbre_F_100) = simulation(100)
(nbre_T_1000, nbre_F_1000) = simulation(1000)
print("Pour 100 parties -> nombre de True : ", nbre_T_100, " - nombre de False : ", nbre_F_100)
print("Pour 1000 parties -> nombre de True : ", nbre_T_1000, " - nombre de False : ", nbre_F_1000)
4. Plus on prend des échantillons de grande taille, plus les effectifs obtenus se rapprochent de ceux calculés avec des probabilités théoriques :
ici 60% de True
et 40% de False
.
Vous pouvez tester avec 10 parties (😢trop petit) ou 1000000 de parties (🤣déjà grand!)
Tester ici
La fonction simulation
n'a pas été écrite, car elle est dans du code caché.
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
À vous de jouer 8 : réaliser des graphiques avec matplotlib
La bibliothèque matplotlib fonctionne avec des listes d'abscisses et d'ordonnées (qui doivent être de même tailles)
1. Tester ci-dessous pour comprendre les syntaxes:
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Votre figure
2. Compléter ci-dessous pour tracer la droite d'équation \(y=2x+1\) pour \(-2 \leq x \leq 3\)
Toutes es listes doivent être écrites en compréhension.
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Votre figure
2. "π à Monte-Carlo"⚓︎
Sujet - π à Monte-Carlo
La méthode de Monte-Carlo est un ensemble de méthodes algorithmiques visant à déterminer la valeur approchée d'une constante en utilisant des procédés aléatoires.
On peut utiliser cette méthode afin de déterminer une valeur approchée de \(\pi\). L'idée est la suivante :
- on considère un carré de \(2\) unités de côtés. Son aire vaut donc \(4\) ;
- on considère un disque de rayon \(1\) centré au centre du carré. Son aire vaut donc \(\pi \times 1^2=\pi\) ;
- on génère un grand nombre de points aléatoires répartis de façon uniforme dans le carré.
Il reste alors à compter le nombre de points à l'intérieur du disque. On peut montrer que leur fréquence tend vers \(\frac{\pi}{4}\) quand le nombre de points aléatoires devient très grand.
Une valeur approchée de \(\pi\) est donc :
On observe ci-dessous le carré de départ ainsi que de nombreux points. On a représenté de couleur différente ceux qui sont dans le cercle et ceux qui n'y sont pas.
On se donne donc :
-
une liste de
nb_points
aléatoires, tous dans le carré décrit ci-dessus. Cette liste est nomméepoints
et chaque point est représenté par ses coordonnées. Par exemple[(-0.5313, 0.0936), (0.9638, 0.3577), ...]
. -
une fonction
distance_origine
prenant en argument les coordonnéesx
ety
d'un point et renvoyant sa distance à l'origine du repère (et donc au centre du cercle)
On demande d'extraire la liste des points situés dans le cercle à l'aide d'une liste en compréhension.
La fonction random
Le module random
de Python propose une fonction random
qui génère des nombres aléatoires uniformément répartis entre 0
et 1
.
👉 On a donc 2 * random()
qui est compris entre 0
et 2
👉 On en déduit que 2 * random() - 1
est compris entre -1
et 1
.
À vous de jouer
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)
Solution
Pour ne pas surcharger le site, nous avons choisi ici nb_points = 1000
. Chez vous, sur votre prpre éditeur Python, vous pouvez tester avec nb_points = 100_000
, pour obtenir une meilleure précision.
from math import sqrt
from random import random
def distance_origine(x, y):
return sqrt(x*x + y*y)
nb_points = 1000
points = [(2 * random() - 1, 2 * random() - 1) for _ in range(nb_points)]
dans_cercle = [p for p in points if distance_origine(p[0], p[1]) <= 1]
# Affiche une valeur approchée de pi
approximation = 4 * len(dans_cercle) / nb_points
print("Pi est environ égal à : ", approximation)
VI Crédits⚓︎
Jean-Louis Thirot, Pierre Marquestaut, Nicolas Revéret et Mireille Coilhac
# Tests
(insensible à la casse)(Ctrl+I)
(Shift+Esc ; Ctrl pour inverser les colonnes)
(Esc)