UKOnline

Liste

Une liste est un type de données qui permet de contenir une liste de valeurs. La manière la plus simple d'en définir une consiste à en préciser toutes les valeurs, dans l'ordre désiré et séparées par des virgules, le tout délimité par des crochets. Une liste vide se déclare simplement avec deux crochets ([]). Une liste contenant, dans l'ordre, les entiers de $1$ à $5$, se déclare comme suit :

La variable numbers contient donc une liste de cinq éléments, chacun étant un nombre entier. La taille d'une liste est le nombre d'éléments qu'elle contient; on peut l'obtenir grâce à la fonction len. On peut afficher une liste avec la fonction print et obtenir son type avec la fonction type :

L'exécution de ces deux instructions dévoile que la variable numbers contient bien une liste de cinq éléments (les nombres entiers de $1$ à $5$) et qu'elle est de type list :

[1, 2, 3, 4, 5]

Chaque élément de la liste possède un indice qui permet d'y accéder, c'est-à-dire d'obtenir sa valeur. Le premier élément d'une liste est celui d'indice $0$, le deuxième celui d'indice $1$...

Pour obtenir un élément de la liste, il suffit de faire suivre le nom de la variable de l'indice désiré entre crochets. L'instruction suivante affiche l'élément à l'indice $0$ de la liste stockée dans la variable numbers, c'est-à-dire son premier élément :

La figure 1 représente visuellement la liste numbers. Vous y voyez clairement qu'il s'agit d'une séquence ordonnée d'éléments, chacun ayant un indice. Le premier indice est $0$ et le dernier indice est $n - 1$, si $n$ représente la taille de la liste.

Liste
Une liste est une séquence ordonnée d'éléments possédant chacun un indice, utilisé pour y accéder.

À l'aide de la fonction len et avec une boucle while, on peut parcourir une liste, c'est-à-dire passer en revue chacun de ses éléments pour, par exemple, les afficher. Pour cela, il suffit d'utiliser une variable comme valeur d'indice, initialisée à $0$ et incrémentée de $1$ jusqu'à atteindre $n - 1$, si $n$ représente la taille de la liste.

L'exemple suivant parcourt tous les éléments de la liste numbers à l'aide d'une boucle while, pour les afficher l'un après l'autre :

En Python, on peut également utiliser un nombre négatif comme indice, pour accéder aux éléments d'une liste à partir de la fin. Ainsi, l'indice $-1$ correspond au dernier élément de la liste, l'indice $-2$ à l'avant-dernier... comme l'illustre la figure 2. Pour parcourir tous les éléments d'une liste à l'envers, on peut écrire la boucle suivante :

Liste indices négatifs
Un indice négatif permet d'accéder aux éléments de la liste en les comptant à partir de la fin.

Enfin, les listes sont hétérogènes, c'est-à-dire que leurs éléments peuvent sans soucis être de types différents. Par exemple, on pourrait représenter une adresse par une liste contenant la rue, le numéro, le code postal, la ville et le pays. Voici comment on pourrait stocker l'adresse du cabinet du Premier ministre belge :

Modification d'une liste

Une fois créée, une liste peut être modifiée en changeant la valeur de ses éléments ou en en supprimant. On peut simplement voir une liste comme plusieurs variables, chacune étant accédée par son indice. Dès lors, on utilise simplement l'opérateur d'affectation pour modifier un élément d'une liste. Par exemple, pour modifier son premier élément, il suffit d'écrire :

Pour supprimer un élément d'une liste, il faut utiliser la fonction prédéfinie del, en lui indiquant l'élément à supprimer. La fonction s'occupera de décaler tous les autres éléments, de sorte qu'il n'y ait pas de « trous » dans la liste. Voyons cela avec l'exemple suivant :

On supprime donc l'élément d'indice $2$, à savoir le troisième élément de la liste. Le résultat de l'exécution de ces trois instructions montre bien que l'élément $3$ a été retiré et que les autres éléments ont été décalés :

[15, 2, 3, 4, 5]
[15, 2, 4, 5]

Slicing

Une autre opération que l'on peut faire sur les listes est le slicing. Elle consiste à extraire une sous-liste à partir d'une liste. On utilise de nouveau les crochets, mais en spécifiant deux indices, à savoir celui du début (inclus) et celui de la fin (non inclus) de la sous-liste à extraire, séparés par un deux-points (:).

Par exemple, pour extraire la sous-liste constituée des deuxième et troisième éléments d'une liste, il faut démarrer à l'indice $1$ et aller jusque l'indice $3$ (c'est-à-dire l'indice $4$ non inclus). L'exemple ci-dessous affiche donc [2, 3, 4] lors de son exécution :

Si on ne précise pas de premier indice, la sous-liste commencera au début de la liste (comme si on avait mis $0$). De même, ne pas indiquer le second indice fera terminer la sous-liste au bout de la liste (comme si on avait mis la taille de la liste). L'exemple suivant affiche [1, 2, 3] et [4, 5], à savoir les trois premiers éléments et les deux derniers :

La figure 3 montre les sous-listes correspondant à plusieurs opérations de slicing effectuées sur une liste. On y voit clairement que le premier indice renseigné est inclus alors que le second est exclu.

Slicing de liste
Le slicing permet d'extraire une sous-liste à partir d'une liste, commençant à un indice (inclus) et se terminant à un autre indice (exclu).

Insertion d'éléments

Le slicing permet également d'insérer des éléments dans une liste. Pour cela, il suffit d'affecter une nouvelle valeur à une sous-liste vide. La valeur à affecter doit être une liste. Analysons l'exemple suivant :

La sous-liste [2:2] ne contient aucun élément. La deuxième instruction remplace cette sous-liste vide par la liste [0], c'est-à-dire qu'on insère la valeur $0$ comme nouvel élément d'indice $2$ dans la liste numbers. Les autres éléments de la liste sont automatiquement décalés. L'exécution du programme affiche :

[1, 2, 0, 3, 4, 5]

La figure 4 illustre comment cette insertion se déroule. On y voit à gauche la sous-liste ainsi que la nouvelle liste qui va la remplacer et à droite le résultat après affectation de la nouvelle valeur à la sous-liste.

Insertion dans une liste
On peut insérer un élément dans une liste en affectant une nouvelle valeur de type liste à une sous-liste de la liste originale.

Voici trois autres exemples qui montrent comment insérer un élément au début et à la fin d'une liste, et comment en modifier un élément quelconque :

La première instruction remplace la sous-liste commençant à l'indice $0$ et se terminant à l'indice $0$ (non inclus), par la sous-liste [0]; c'est-à-dire que l'élément $0$ est inséré en début de liste. La troisième instruction, quant à elle, insère l'élément $6$ en fin de liste. Enfin, la cinquième instruction remplace l'élément d'indice $3$ par $42$. On aurait évidemment pu simplement écrire numbers[3] = 42. L'exécution de ces instructions affiche donc :

[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 42, 4, 5, 6]

Notez que l'on peut simplement utiliser numbers[:0] pour insérer un élément au début d'une liste et numbers[len(numbers):] pour insérer un élément à sa fin. En utilisant le slicing, on peut également remplacer ou insérer plusieurs éléments en une fois, étant donné qu'on remplace en fait une sous-liste par une nouvelle liste. Voici, par exemple, comment remplacer les quatre derniers éléments d'une liste par deux éléments :

Une fois la première instruction exécutée, la liste contiendra alors cinq éléments au lieu de sept. L'exécution des deux instructions affiche :

[0, 1, 2, 3, 4]

Les trois premiers éléments de la liste ont été conservés et la sous-liste des quatre derniers éléments a été remplacée par la liste [3, 4].

Suppression d'éléments

On peut supprimer plusieurs éléments d'une liste en combinant la fonction del avec l'opérateur de slicing. Voici un exemple où l'on supprime tous les éléments de la liste, sauf le premier et le dernier :

Le résultat de l'exécution de ces trois instructions montre bien que les trois éléments centraux de la liste ont été supprimés :

[1, 5]

La fonction del permet en fait de supprimer une variable de la mémoire. L'exemple suivant provoque une erreur d'exécution car on tente d'afficher une variable qui n'existe plus, puisqu'elle a été supprimée :

Traceback (most recent call last):
  File "program.py", line 3, in <module>
    print(a)
NameError: name 'a' is not defined

Concaténation et répétition

Il est possible de créer une nouvelle liste en concaténant deux listes existantes. On utilise pour cela l'opérateur de concaténation (+) comme pour les chaines de caractères. L'exemple suivant crée une nouvelle liste en en concaténant deux existantes :

On peut également construire une liste en répétant plusieurs fois une liste, c'est-à-dire la concaténer plusieurs fois d'affilées. On utilise pour cela l'opérateur de copie (*), comme dans l'exemple suivant :

L'effet de l'opérateur de copie est que la liste [1, 2] est copiée quatre fois, ces copies étant ensuite concaténées pour créer une nouvelle liste. L'exécution de ces deux instructions affiche donc :

[1, 2, 1, 2, 1, 2, 1, 2]

Appartenance

On doit souvent tester si un élément donné appartient à une liste ou non, c'est-à-dire si cet élément fait partie de ceux de la liste. Une solution immédiate à ce problème consiste à utiliser une boucle pour parcourir les éléments de la liste et rechercher celui qu'on veut. On pourrait, par exemple, définir une fonction contains qui fait ce travail :

La boucle compare chaque élément de la liste (data) avec la valeur recherchée (element). Si on l'a trouvée, on quitte immédiatement la fonction en renvoyant la valeur True. Sinon, on finit par atteindre la fin du corps de la fonction et on renvoie False. Mais Python propose en fait un opérateur d'appartenance (in) qui permet de directement tester si un élément fait partie d'une liste ou non. Les deux instructions suivantes sont équivalentes et affichent toutes les deux True :

On peut également tester si un élément ne fait pas partie d'une liste en utilisant not in. Les deux instructions suivantes sont équivalentes et affichent toutes les deux False :

Copie

Si on souhaite faire une copie d'une liste, on ne peut pas s'y prendre n'importe comment. Voyons l'exemple suivant :

La première instruction crée une liste de trois éléments et la stocke dans la variable a. Vient ensuite la deuxième instruction dont on pourrait penser qu'elle fait une copie de la liste stockée dans a pour la stocker dans b. On modifie ensuite le premier élément de la liste a et on affiche les deux listes. Voici le résultat de l'exécution de ces instructions :

[42, 2, 3]
[42, 2, 3]

On voit que les listes a et b sont toutes les deux modifiées, car il n'y a en fait pas eu de copie de la liste. Les variables a et b permettent d'accéder à la même liste en mémoire, comme l'illustre la figure 5. Une variable contient en fait une référence vers la zone mémoire où se trouve stockée la valeur qu'elle représente, et pas la valeur directement. Ce sont ces adresses mémoires qui sont pareilles dans les variables a et b.

Alias
Un alias est une variable qui réfère une liste déjà référée par une autre variable, les deux variables permettant donc d'accéder à la même liste.

Pour réaliser une copie d'une liste, on peut utiliser le slicing. En effet, pour rappel, le slicing extrait une nouvelle liste correspondant à une sous-liste. Dès lors, pour faire une copie d'une liste existante, il suffit de faire un slicing qui reprend simplement toute la liste. On spécifie pour cela les bornes $0$ et la longueur de la liste, ou juste rien. Analysons l'exemple suivant :

On commence par créer une copie de la liste a que l'on stocke dans la variable b. On fait ensuite une copie de la liste b que l'on stocke dans la variable c. On modifie ensuite les listes a et b pour enfin afficher les valeurs des trois listes. Au vu du résultat de l'exécution, on peut confirmer qu'on a bien fait des copies des listes :

[-1, 2, 3]
[-2, 2, 3]
[1, 2, 3]

Comparaison

Enfin, un dernier type d'opération que l'on peut vouloir faire entre deux listes consiste à les comparer. Pour tester si deux listes sont identiques, il suffit d'utiliser l'opérateur d'égalité (==). Deux listes sont égales si elles possèdent le même nombre d'éléments et que ceux situés aux mêmes indices sont égaux.

On peut également comparer deux listes en utilisant les opérateurs >, <, >= et <=. Dans ce cas, les listes sont comparées en suivant l'ordre lexicographique. Les premiers éléments de chaque liste sont d'abord comparés entre eux. Si celui de la première liste est plus petit (resp. plus grand) que celui de la seconde liste, alors la première liste est plus petite (resp. plus grande) que la seconde. Si les premiers éléments sont égaux, alors la comparaison continue avec les deuxièmes éléments...

L'exemple suivant montre plusieurs exemples de comparaisons entre deux listes :

Comme vous pouvez le constater avec la troisième comparaison faite, si tous les éléments de deux listes sont égaux mais qu'une des deux listes possède moins d'éléments que l'autre, alors elle est d'office plus petite que l'autre liste.