Une liste est une "collection" d'objets indicés.
Les exemples ci-dessous illustrent la façon dont les éléments sont indicés. Vous retiendrez également de ces exemples les diverses méthodes de parcours des éléments de la liste.
# une liste de nombres
a=[2, 10, 5//3, 7.2, 8]
print("Longueur de la liste a : ", len(a) )
print("La liste : ", a)
print("Contenu, élément un à un : ", a[0],a[1],a[2],a[3], a[4])
print('\n')
print('Parcours des éléments avec une boucle sur les indices :')
for i in range(len(a)) :
print(a[i],end=', ')
print('\n')
print('Parcours des éléments avec une boucle sans les indices :')
for x in a :
print(x,end='; ')
print('\n')
print('Parcours des éléments avec indices et éléments :')
for i,x in enumerate(a) :
print("Le terme d'indice {} est {}.".format(i,x) )
On obtient :
Longueur de la liste a : 5
La liste : [2, 10, 1, 7.2, 8]
Contenu, élément un à un : 2 10 1 7.2 8
Parcours des éléments avec une boucle sur les indices :
2, 10, 1, 7.2, 8,
Parcours des éléments avec une boucle sans les indices :
2; 10; 1; 7.2; 8;
Parcours des éléments avec indices et éléments :
Le terme d'indice 0 est 2.
Le terme d'indice 1 est 10.
Le terme d'indice 2 est 1.
Le terme d'indice 3 est 7.2.
Le terme d'indice 4 est 8.
On retiendra que les indices, comme pour les chaînes de caractères, commencent à zéro et non à un. Le dernier indice est donc len(a)-1 et non len(a).
Autre exemple :
def f(x) :
return 5*x**2+3*x+1
# une liste contenant divers objets :
a=[2, 'coucou', f, f(7)]
print("Longueur de la liste a : ", len(a) )
print("La liste : ", a)
print('\n')
print('Les éléments de la liste :')
for i, x in enumerate(a) :
print("Le terme d'indice {} est {}.".format(i,x))
print('\n')
print('Les types des éléments de la liste :')
for i, x in enumerate(a) :
print( "Le type du terme d'indice {} est {}.".format(i,type(x)) )
print('\n')
On obtient :
Longueur de la liste a : 4
La liste : [2, 'coucou', function f at 0x7f29b4ab8bf8, 267]
Les éléments de la liste :
Le terme d'indice 0 est 2.
Le terme d'indice 1 est coucou.
Le terme d'indice 2 est function f at 0x7f29b4ab8bf8.
Le terme d'indice 3 est 267.
Les types des éléments de la liste :
Le type du terme d'indice 0 est class 'int'.
Le type du terme d'indice 1 est class 'str'.
Le type du terme d'indice 2 est class 'function'.
Le type du terme d'indice 3 est class 'int'.
Une liste peut donc contenir des objets de types différents.
Modifier les éléments d'une liste
Modifier la valeur d'un élément d'indice connu.
L=['ba', 'be', 'bi', 'bo', 'bu']
L[2]='fifi'
print(L)
La liste L est modifiée :
['ba', 'be', 'fifi', 'bo', 'bu']
Effacer un élément d'indice connu.
L=['ba', 'be', 'bi', 'bo', 'bu']
del(L[3])
print(L)
L'élément d'indice 3 est ainsi effacé :
['ba', 'be', 'bi', 'bu']
On peut également utiliser pop :
L=['ba', 'be', 'bi', 'bo', 'bu']
L.pop(3)
print(L)
On obtient :
['ba', 'be', 'bi', 'bu']
Avec pop, on peut en fait également récupérer la valeur de l'élément supprimé en même temps :
L=['ba', 'be', 'bi', 'bo', 'bu']
a=L.pop(3)
print(L)
print(a)
On obtient :
['ba', 'be', 'bi', 'bu']
bo
Récupérer l'indice d'un élément.
Si on l'on veut connaître l'indice d'un élément présent dans la liste L, on peut utiliser index :
L=['ba', 'be', 'bi', 'bo', 'bu']
k=L.index('bo')
print(k)
Ce qui donne :
3
Si l'élément a plusieurs occurrences dans la liste L, L.index() renverra le plus petit indice correspondant.
L=['ba', 'be', 'bi', 'bo', 'bu', 'bo', 'by', 'bo']
k=L.index('bo')
print(k)
Ce qui donne :
3
Si l'élément n'est pas présent dans la liste, python renvoie une erreur :
L=['ba', 'be', 'bi', 'bu', 'by']
k=L.index('bo')
print(k)
donne :
ValueError: 'bo' is not in list
Pour éviter une erreur, on peut utiliser count qui permet de retourner le nombre d'éléments de valeur donnée présents dans la liste.
L=['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
compteur=L.count('bo')
print("Nombre de 'bo' présents dans la liste L : ",compteur)
donne :
Nombre de 'bo' présents dans la liste L : 2
et pour éviter une erreur en cas d'absence de la valeur :
L=['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
if L.count('bo')>0 :
print("Premier indice de 'bo' dans la liste L : ", L.index('bo') )
else :
print("Aucun 'bo' dans cette liste.")
Effacer un élément d'indice inconnu.
Avec remove, on peut supprimer la première occurrence d'une valeur donnée dans la liste. Attention, python retourne une erreur si la valeur n'était pas présente.
L=['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
if L.count('bo')>0 :
L.remove('bo')
print("Liste L après remove : ", L )
else :
print("La liste ne contenait aucun 'bo'.")
donne :
Liste L après remove : ['ba', 'be', 'bi', 'bu', 'by', 'bo']
Ajouter un élément à une liste
append()
On ajoute un élément à une liste L avec L.append(valeur à ajouter). La nouvelle valeur est insérée en fin de liste (et devient donc le dernier élément de la liste après modification) :
L=['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
L.append('foo')
print(L)
L.append(7)
print(L)
L'affichage obtenu :
['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo', 'foo']
['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo', 'foo', 7]
insert()
On peut insérer un élément à une position précise dans une liste avec insert(position, valeur à insérer) :
L=['ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
L.insert(0,'foo')
print(L)
L.insert(2,'fii')
print(L)
L.insert(len(L), 'un ajout à la fin')
print(L)
L'affichage obtenu :
['foo', 'ba', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
['foo', 'ba', 'fii', 'bo', 'be', 'bi', 'bu', 'by', 'bo']
['foo', 'ba', 'fii', 'bo', 'be', 'bi', 'bu', 'by', 'bo', 'un ajout à la fin']
extend()
On peut ajouter les éléments d'une liste M à une liste L :
L=['ba', 'bo', 'be', 'bi', 'bu', 'by']
M=[ 4.8, 9.3, 7.2]
L.extend(M)
print(L)
L'affichage obtenu :
['ba', 'bo', 'be', 'bi', 'bu', 'by', 4.8, 9.3, 7.2]
Concaténation de listes
Il est possible de concaténer deux listes pour en former une troisième.
L=['ba', 'bo', 'be', 'bi', 'bu', 'by']
M=[ 4.8, 9.3, 7.2]
N=L+M
P=M+L
print("Liste N : ", N)
print("Liste P : ", P)
L'affichage obtenu :
Liste N : ['ba', 'bo', 'be', 'bi', 'bu', 'by', 4.8, 9.3, 7.2]
Liste P : [4.8, 9.3, 7.2, 'ba', 'bo', 'be', 'bi', 'bu', 'by']
Copier une liste
Il est important de comprendre la différence entre une instruction L= M dans laquelle M est une liste et cette même instruction lorsque M est par exemple de type int, float, str.
Ces différences et les "pièges" à éviter sont à découvrir ici.
Changer de type
Il pourra parfois être utile de fabriquer une liste à partir d'un objet qui n'en est pas un.
Nous nous contenterons ici d'un seul exemple.
t='Zorglub'
print(t)
t=list(t)
print(t)
L'affichage obtenu :
Zorglub
['Z', 'o', 'r', 'g', 'l', 'u', 'b']
Listes en compréhension
Étant donné une liste d’entiers telle que t=[5, 2, 0, 3, 7, 10], on cherche à construire la liste L dont les éléments sont 10 fois les éléments de t, c’est-à-dire [50, 20, 0, 30, 70, 100].
Voici un code Python répondant au problème :
t = [5, 2, 0, 3, 7, 10]
print(t)
L = [10 * x for x in t]
print(L)
Ce qui donne :
[5, 2, 0, 3, 7, 10]
[50, 20, 0, 30, 70, 100]
A la ligne 3, est définie une liste L dite liste en compréhension.
Une liste en compréhension L a la syntaxe minimale suivante : [expr for x in t]
où
la paire de crochets, les mots-clefs for et in sont obligatoires
t est, par exemple, une liste (voir plus bas pour d’autres possibilités)
x est l’élément courant qui parcourt la liste t ; x est appelé variable de contrôle de la liste en compréhension
expr est une expression qui dépend en général de x et dont la valeur est placée dans L
Si t est un conteneur (une liste, une chaîne, etc), la liste en compréhension L avec la syntaxe ci-dessus a toujours même nombre d’éléments que le conteneur t.
Intérêt d’une liste en compréhension : générer une liste en une seule expression et non en une ou plusieurs instructions. L’intérêt des listes en compréhension est avant tout leur compacité d’édition dans le code et leur bonne lisibilité.
Vocabulaire : la documentation officielle en français a utilisé jusqu’à la version 3.9 de Python le terme assez incompréhensible de « compréhension de liste » pour finalement adopter le terme de « liste en compréhension ». On rencontre aussi parfois le terme de liste en intension censé s’opposer à l’expression liste en extension ce dernier signifiant, grosso modo, liste littérale, voir cette discussion.
Liste en compréhension et boucle for
Une liste en compréhension admet un équivalent créé avec une boucle for mais nécessitant un code plus long.
Soit la liste en compréhension L suivante :
t = [5, 2, 0, 3, 7, 10]
L = [10 * x for x in t]
print(L)
Ce qui donne :
[50, 20, 0, 30, 70, 100]
Elle pourrait être obtenue avec une boucle for :
t = [5, 2, 0, 3, 7, 10]
L = []
for x in t:
L.append(10*x)
print(L)
Ce qui donne :
[50, 20, 0, 30, 70, 100]
La liste L est obtenue en trois lignes de code au lieu d’une.
Listes en compréhension à partir d’un itérable
Une liste en compréhension est souvent construite sur la base d’une liste mais on peut construire une liste en compréhension sur la base de n’importe quel itérable.
Par exemple, on peut construire une liste en compréhension à partir d’une chaîne
w = "SERPENT"
L = [2 * c for c in w]
print(L)
Ce qui donne :
['SS', 'EE', 'RR', 'PP', 'EE', 'NN', 'TT']
Listes en compréhension et la clause if
Il existe une variante dans la syntaxe des listes de compréhension utilisant une clause if.
Par exemple, étant donné une liste L d’entiers, soit à construire la liste t obtenue en ne gardant que les entiers x de L tel que x > 42 :
t = [65, 31, 9, 32, 81, 82, 46, 12]
L = [x for x in t if x >= 42]
print(L)
Ce qui donne :
[65, 81, 82, 46]
x varie dans t et est inséré dans la liste L en construction si x ≥ 42.
On pourrait même écrire tout le code en une seule ligne.
L’équivalent avec une boucle for serait le suivant :
t = [65, 31, 9, 32, 81, 82, 46, 12]
L= []
for x in t:
if x >= 42:
L.append(x)
print(L)
Listes en compréhension imbriquées
Des listes en compréhension peuvent être imbriquées. Néanmoins la liste n’est pas forcément créée dans l’ordre où on s’y attendrait.
Soit à créer une liste formée de tous « mots » commençant par une lettre A ou B et suivie d’un chiffre parmi 1, 2 ou 3.
On peut utiliser une liste en compréhension :
L = [x+y for x in "AB" for y in "123"]
print(L)
Ce qui donne :
['A1', 'A2', 'A3', 'B1', 'B2', 'B3']
Le résultat montre que l’on fixe d’abord la lettre, c’est-à-dire les éléments du for lexicalement le plus interne (ici for x) puis que y varie. Ce n’est pas forcément très intuitif.
Le résultat est plus facilement compréhensible si la liste en compréhension est interprétée par deux boucles for imbriquées exactement dans l’ordre où on lit les apparitions des for dans la liste en compréhension, ce qui donne ici :
L = []
for x in "AB":
for y in "123":
L.append(x+y)
print(L)
Ce qui donne :
['A1', 'A2', 'A3', 'B1', 'B2', 'B3']
la boucle for x apparaît avant la boucle for y, dans le même ordre que la liste en compréhension [x+y for x in "AB" for y in "123"].
Création d’un tableau 2D initialisé
Une liste en compréhension est un moyen très simple de créer un conteneur pour un tableau ayant n lignes et p colonnes. Le code ci-dessous crée un tableau à 2 lignes et 3 colonnes initialisé avec des 0 :
L = [[0 for j in range(3)] for i in range(2)]
print(L)
L[1][2]=42
print(L)
Ce qui donne :
[[0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 42]]
On crée une liste de 2 lignes, chaque ligne étant une liste de 3 éléments. L’indice i parcourt les lignes et l’indice j parcourt chaque colonne de chaque ligne.
Au passage, comme l’élément le plus interne dans les listes est immuable (il s’agit de l’entier 0), on peut même simplifier la syntaxe :
L = [[0]*3 for i in range(2)]
print(L)
L[1][2]=42
print(L)
Ce qui donne :
[[0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 42]]
Confusion possible
Attention toutefois que le code suivant lui ne donne pas le résultat attendu :
L = [[0]*3]*2
print(L)
L[1][2]=42
print(L)
Ce qui donne :
[[0, 0, 0], [0, 0, 0]]
[[0, 0, 42], [0, 0, 42]]
Code équivalent
Voici l’équivalent du code correct donné en début de section sans utiliser de liste en compréhension et en utilisant deux boucles for imbriquées. On notera que le code est plus long :
L=[]
for i in range(2):
lig = []
for j in range(3):
lig.append(0)
L.append(lig)
print(L)
Ce qui donne :
[[0, 0, 0], [0, 0, 0]]
Listes en compréhension imbriquées et clause if
Soit à placer dans une liste L tous les couples d’entiers (x,y) tel que 0 ≤ x,y ≤ 3 et x + y ≤ 3.
Voici un code utilisant une liste en compréhension :
a = 3
L =[[x,y] for x in range(0,a+1) for y in range(0,a+1) if x+y <= a]
print(L)
Ce qui donne :
[[0, 0], [0, 1], [0, 2], [0, 3], [1, 0],
[1, 1], [1, 2], [2, 0], [2, 1], [3, 0]]
La syntaxe de la liste en compréhension a été prévue pour que la traduction depuis des boucles for imbriquées soit immédiate : on place les for et if dans l’ordre de gauche à droite où ils apparaissent dans la liste en compréhension :
a = 3
L =[]
for x in range(0,a+1):
for y in range(0,a+1):
if x+y <= a:
L.append([x,y])
print(L)
Ce qui donne :
[[0, 0], [0, 1], [0, 2], [0, 3], [1, 0],
[1, 1], [1, 2], [2, 0], [2, 1], [3, 0]]
Les tuples correspondent aux listes à la différence qu'ils sont non modifiables. On a vu à la section précédente que les listes pouvaient être modifiées par des références; les tuples vous permettent de vous affranchir de ce problème. Pratiquement, ils utilisent les parenthèses au lieu des crochets :
>>> x = (1,2,3)
>>> x
(1, 2, 3)
>>> x[2]
3
>>> x[0:2]
(1, 2)
>>> x[2] = 15
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment
L'affectation et l'indiçage fonctionne comme avec les listes, mais si l'on essaie de modifier un des éléments du tuple, Python renvoie un message d'erreur. Si vous voulez ajouter un élément (ou le modifier), vous devez créer un autre tuple :
>>> x = (1,2,3)
>>> x + (2,)
(1, 2, 3, 2)
Remarquez que pour utiliser un tuple d'un seul élément, vous devez utiliser une syntaxe avec une virgule (element,), ceci pour éviter une ambiguïté avec une simple expression. Autre particularité des tuples, il est possible d'en créer de nouveaux sans les parenthèses, dès lors que ceci ne pose pas d'ambiguïté avec une autre expression :
>>> x = (1,2,3)
>>> x
(1, 2, 3)
>>> x = 1,2,3
>>> x
(1, 2, 3)
Toutefois, nous vous conseillons d'utiliser systématiquement les parenthèses afin d'éviter les confusions.
Enfin, on peut utiliser la fonction tuple(sequence) qui fonctionne exactement comme la fonction list, c-à-d qu'elle prend en argument un objet séquentiel et renvoie le tuple correspondant :
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> tuple(range(10))
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> tuple("ATGCCGCGAT")
('A', 'T', 'G', 'C', 'C', 'G', 'C', 'G', 'A', 'T')
Remarque : les listes, dictionnaires, tuples sont des objets qui peuvent contenir des collections d'autres objets. On peut donc construire des listes qui contiennent des dictionnaires, des tuples ou d'autres listes, mais aussi des dictionnaires contenant des tuples, des listes, etc.
Les dictionnaires se révèlent très pratiques lorsque vous devez manipuler des structures complexes à décrire et que les listes présentent leurs limites. Les dictionnaires sont des collections non ordonnées d'objets, c-à-d qu'il n'y a pas de notion d'ordre (i. e. pas d'indice). On accède aux valeurs d'un dictionnaire par des clés. Ceci semble un peu confus ? Regardez l'exemple suivant :
>>> ani1 = {}
>>> ani1['nom'] = 'girafe'
>>> ani1['taille'] = 5.0
>>> ani1['poids'] = 1100
>>> ani1
{'nom': 'girafe', 'poids': 1100, 'taille': 5.0}
>>> ani1['taille']
5.0
En premier, on définit un dictionnaire vide avec les symboles {} (tout comme on peut le faire pour les listes avec []). Ensuite, on remplit le dictionnaire avec différentes clés auxquelles on affecte des valeurs (une par clé). Vous pouvez mettre autant de clés que vous voulez dans un dictionnaire (tout comme vous pouvez ajouter autant d'éléments que vous voulez dans une liste). Pour récupérer la valeur d'une clé donnée, il suffit d'utiliser une syntaxe du style dictionnaire['cle'].
Méthodes keys() et values()
Les méthodes keys() et values() renvoient, comme vous vous en doutez, les clés et les valeurs d'un dictionnaire (sous forme de liste) :
>>> ani1.keys()
['nom', 'poids', 'taille']
>>> ani1.values()
['girafe', 1100, 5.0]
On peut aussi initialiser toutes les clés d'un dictionnaire en une seule opération :
>>> ani2 = {'nom':'singe', 'poids':70, 'taille':1.75}
Liste de dictionnaires
En créant une liste de dictionnaires possédant les mêmes clés, on obtient une structure qui ressemble à une base de données :
>>> animaux = [ani1, ani2]
>>> animaux
[{'nom': 'girafe', 'poids': 1100, 'taille': 5.0}, {'nom': 'singe', 'poids': 70, 'taille': 1.75}]
>>>
>>> for ani in animaux:
... print ani['nom']
...
girafe
singe
Existence d'une clef
Enfin, pour vérifier si une clé existe, vous pouvez utiliser :
>>> if "poids" in ani2:
... print("La clef 'poids' existe pour ani2")
...
La clef 'poids' existe pour ani2
ou la propriété has_key() (uniquement sous Python 2) :
>>> if ani2.has_key('poids'):
... print "La clef 'poids' existe pour ani2"
...
La clef 'poids' existe pour ani2
Vous voyez que les dictionnaires permettent de gérer des structures complexes de manière plus explicite que les listes.
Dictionnaire en compréhension
Il est également possible de créer un dictionnaire en compréhension en construisant un couple clé : valeur à partir d’une itération :
liste = ["liste", "avec", "des", "mots"]
dictionnaire = {len(e) : e for e in liste}
print(dictionnaire)
# Affiche {5: 'liste', 4: 'mots', 3: 'des'}
Par exemple, on peut ainsi inverser la clé et la valeur
dictionnaire = {"pomme": 8, "poire": 3, "orange": 7}
nouveau_dict = {v : k for k, v in dictionnaire.items()}
print(nouveau_dict)
# Affiche {8: 'pomme', 3: 'poire', 7: 'orange'}