Types itérables

Valeurs itérables et construction for .. in ..:

Il est possible d'égréner un à un les éléments d'une liste à l'aide d'une boucle.

In [ ]:
L = [1, 4, 9, 16, 25, 36]
i = 0
while i < len(L):
    print(L[i])
    i = i + 1 
1
4
9
16
25
36

Un nouvel élément de L est traité à chaque nouvelle itération. On dit que les listes python sont des valeurs itérables. Le type list est l'exemple le plus évident de type itérable, mais comme nous allons voir, ce n'est pas le seul.

Le langage Python dispose d'une syntaxe simplifiée pour itérer les éléments d'un itérable.

In [ ]:
L = [1, 4, 9, 16, 25, 36]
for x in L:
    print(x)
1
4
9
16
25
36

La boucle exécutée autant de fois qu'il y a d'éléments dans l'itérable. L'affectation d'un élément à la variable x est implicite. À chaque nouvelle itération, x reçoit pour valeur l'élément suivant de l'itérable.

Le type range est un autre exemple de type itérable.

Si $a$ et $b$ sont des entiers alors range(a, b) représente l'intervalle $[\![a,\,b[\![$ :

$$n\in[\![a,\,b[\![\quad\Longleftrightarrow\quad a\leq n\lt b.$$
In [ ]:
for x in range(5, 10):
    print(x)
5
6
7
8
9

Remarques :

  • Il faut bien noter que l'intervalle est fermé à gauche et ouvert à droite.

  • Un intervalle n'est pas une liste. La place mémoire occupée par une valeur de type range est toute petite et est indépendante de la longueur de l'intervalle.

L'écriture range(b) est équivalente à range(0, b) :

In [ ]:
for x in range(4):
    print(x)
0
1
2
3

Pour parcourir une liste nous avons deux options à notre disposition.

(a) On peut itérer sur les éléments de la liste :

In [ ]:
for x in L:
    print(x)
1
4
9
16
25
36

(b) On peut aussi itérer sur les indices de la liste :

In [ ]:
for i in range(len(L)):
    print(L[i])
1
4
9
16
25
36

La première solution est beaucoup plus claire et lisible. Elle est donc à privilégier lorsque les indices des éléments ne sont pas utiles.

Exemple : Calcul de la somme des éléments de la liste L :

In [ ]:
s = 0
for x in L:
    s = s + x
print(s)
91

Par contre dans l'exemple suivant la connaissance de l'indice des éléments est nécessaire.

Exemple : Calcul de la somme des éléments de L en position paire :

In [ ]:
s = 0
for i in range(len(L)):
    if i % 2 == 0:
        s = s + L[i]
print(s)
35

Test d'appartenance à un itérable

L'opérateur in permet également de tester l'appartenance d'une valeur à un itérable :

In [ ]:
24 in L
Out[ ]:
False
In [ ]:
25 in L
Out[ ]:
True
In [ ]:
637 in range(1000000)
Out[ ]:
True

Pour ce dernier exemple, on préfèrera écrire 0 <= 637 < 1000000 qui est plus clair et plus efficace.

Exemple : Calcul de la somme des éléments communs à L1 et L2 :

In [ ]:
L1 = [4, 7, 2, 9]
L2 = [3, 11, 9, 1, 7]
s = 0
for x in L1:
    if x in L2:
        s = s + x
print(s)
16

Il faut avoir conscience que pour évaluer l'expression x in L2, Python doit parcourir un à un tous les éléments de L2. Ceci peut être coûteux en temps d'exécution si la liste est de grande taille.

Définition de listes en compréhension

Supposons que nous devions créer une liste L contenant les carrés des entiers naturels compris entre 1 et 15. Une solution possible est de créer une liste vide puis d'ajouter une à une les valeurs à l'aide de la fonction append :

In [ ]:
L = []
for i in range(1, 16):
    L.append(i ** 2)
print(L)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225]

Le langage python propose une construction élégante pour obtenir le même effet :

In [ ]:
L = [i ** 2 for i in range(1, 16)]
print(L)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225]

De façon littérale : L est la liste des i ** 2 pour i appartenant à range(1, 16).

Pour créer une liste dont tous les éléments sont égaux à 0 on peux écrire :

In [ ]:
[0 for i in range(10)]
Out[ ]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Pour souligner le fait que la variable de boucle i ne sert pas, une convention est d'utiliser le nom _ :

In [ ]:
[0 for _ in range(10)]
Out[ ]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Une autre possibilité est d'écrire :

In [ ]:
[0] * 10
Out[ ]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Les flux d'entrée/sortie sont aussi des itérables

Voici le code python que nous avions écrit pour lire et traiter une à une toutes les lignes d'un fichier de texte :

In [ ]:
fd = open("quantique.txt", "r")
ligne = fd.readline()       # Lecture de la première ligne
while ligne != '':          # Tant que EOF n'est pas atteint
    nom = ligne.upper()     #     Traitement
    print(nom)              #     de la ligne
    ligne = fd.readline()   #     Lecture de la ligne suivante
fd.close()
MAX PLANCK

ERWIN SCHRÖDINGER

ALBERT EINSTEIN

WERNER HEISEINBERG

LOUIS DE BROGLIE

NIELS BOHR

La valeur flux retournée par la fonction open est une valeur itérable. Les éléments de cet itérable sont les lignes du fichier de texte. On peut donc écrire beaucoup plus simplement :

In [ ]:
fd = open("quantique.txt", "r")
for ligne in fd:
    nom = ligne.upper()     #     Traitement
    print(nom)              #     de la ligne
fd.close()
MAX PLANCK

ERWIN SCHRÖDINGER

ALBERT EINSTEIN

WERNER HEISEINBERG

LOUIS DE BROGLIE

NIELS BOHR