Les listes en Python : Guide complet

En Python 3, la structure de données list est un type de séquence mutable fondamental et largement utilisé. Elle permet de stocker une collection ordonnée d'éléments. Ce guide explore ses caractéristiques essentielles, ses opérations courantes, ses considérations de performance et les bonnes pratiques.

Caractéristiques principales

  • Ordonnée : Les éléments conservent leur ordre d'insertion et sont accessibles via un indice numérique.
  • Mutable : Une liste peut être modifiée après sa création (ajout, suppression, modification d'éléments).
  • Types d'éléments hétérogènes : Une même liste peut contenir des éléments de types différents (entiers, chaînes de caractères, autres listes, etc.).
  • Taille dynamique : Les listes ne sont pas limitées par une taille fixe et peuvent croître ou décroître selon les besoins.
  • Itérable : Les listes supportent les boucles for, les compréhensions de liste et d'autres opérations d'itération.

Création de listes


# Liste vide
liste_vide = []

# Liste avec valeurs initiales
nombres = [1, 2, 3]
mixte = [1, "bonjour", 3.14, [4, 5]]

# Utilisation du constructeur list()
caracteres = list("abc")   # Produit ['a', 'b', 'c']
sequences = list(range(5))  # Produit [0, 1, 2, 3, 4]

# Compréhension de liste
carres = [x ** 2 for x in range(5)]   # Produit [0, 1, 4, 9, 16]
   

Opérations courantes

Accès et modification


ma_liste = [10, 20, 30, 40]
print(ma_liste[0])    # Affiche 10
print(ma_liste[-1])   # Affiche 40 (l'indexation négative compte à partir de la fin)

# Modification d'un élément
ma_liste[1] = 25      # ma_liste devient [10, 25, 30, 40]

# Extraction d'une sous-liste (slice) - crée une nouvelle liste
sous_liste = ma_liste[1:3]   # Produit [25, 30]
   

Ajout d'éléments


ma_liste = [1, 2]
ma_liste.append(3)          # ma_liste est maintenant [1, 2, 3] (ajout à la fin)
ma_liste.extend([4, 5])     # ma_liste est maintenant [1, 2, 3, 4, 5] (fusionne une autre liste)
ma_liste.insert(1, 99)      # ma_liste est maintenant [1, 99, 2, 3, 4, 5] (insertion à un indice spécifique)
   

Suppression d'éléments


ma_liste = [10, 20, 30, 20]
ma_liste.remove(20)         # Supprime la première occurrence de 20 -> [10, 30, 20]
element_supprime = ma_liste.pop()     # Supprime et retourne le dernier élément. pop(0) supprime le premier.
del ma_liste[0]             # Supprime l'élément à l'indice 0.
ma_liste.clear()            # Vide complètement la liste.
   

Recherche et comptage


ma_liste = [5, 2, 9, 2]
indice = ma_liste.index(2)           # Retourne l'indice de la première occurrence de 2 -> 1
nombre_occurrences = ma_liste.count(2) # Retourne 2
presence = 2 in ma_liste             # Retourne True si 2 est dans la liste
   

Tri et inversion


ma_liste = [3, 1, 4, 1, 5, 9, 2]
ma_liste.sort()             # Trie la liste sur place par ordre croissant -> [1, 1, 2, 3, 4, 5, 9]
ma_liste.sort(reverse=True) # Trie sur place par ordre décroissant -> [9, 5, 4, 3, 2, 1, 1]
ma_liste.reverse()          # Inverse l'ordre des éléments sur place -> [1, 1, 2, 3, 4, 5, 9]

# Pour obtenir une nouvelle liste triée/inversée sans modifier l'originale
liste_triee = sorted(ma_liste)
liste_inversee = list(reversed(ma_liste))
   

Copie de listes


original = [1, 2, [3, 4]]
copie_superficielle = original.copy()   # Copie superficielle : la liste interne est toujours une référence
# Modification de la liste interne dans la copie affecte l'originale
copie_superficielle[2][0] = 99
# original est maintenant [1, 2, [99, 4]]

import copy
copie_profonde = copy.deepcopy(original) # Copie profonde : crée des copies indépendantes de tous les objets
# Modification de la liste interne dans la copie profonde n'affecte pas l'originale
copie_profonde[2][0] = 100
# original reste [1, 2, [99, 4]]
   

Complexité temporelle des opérations courantes

Opération Complexité moyenne Description
liste[i] (accès par indice) O(1) Accès direct à l'élément.
liste.append(x) O(1) Ajout à la fin. Peut nécessiter une réallocation périodique, mais amortie à O(1).
liste.pop() O(1) Suppression du dernier élément.
liste.pop(i) / liste.insert(i, x) O(n) La suppression ou l'insertion au milieu nécessite de décaler les éléments suivants.
del liste[i] O(n) Similaire à pop(i) en termes de décalage d'éléments.
x in liste O(n) Recherche linéaire séquentielle.
liste.sort() O(n log n) Utilise l'algorithme Timsort, très efficace.
Extraction par tranche liste[a:b] O(k) k = b-a. Crée une nouvelle liste contenant k éléments.

Compréhensions de liste

Les compréhensions de liste offrent une syntaxe concise et performante pour créer des listes.


# Méthode traditionnelle avec boucle for
carres_traditionnel = []
for x in range(10):
   carres_traditionnel.append(x ** 2)

# Idem avec une compréhension de liste
carres_comprehension = [x ** 2 for x in range(10)]

# Avec une condition
nombres_pairs = [x for x in range(20) if x % 2 == 0]

# Boucles imbriquées
paires = [(x, y) for x in [1, 2] for y in [3, 4]] # Produit [(1, 3), (1, 4), (2, 3), (2, 4)]
   

Points d'attention

  • Copie superficielle : Lorsque vous copiez une liste contenant des objets mutables (comme d'autres listes), .copy() ou list() ne créent que des copies de références aux objets internes. Modifier ces objets internes dans la copie affectera également l'original. Utilisez copy.deepcopy() pour une indépendance totale.
  • Paramètres par défaut mutables dans les fonctions : Évitez d'utiliser des listes comme paramètres par défaut dans les définitions de fonctions (par exemple, def ma_fonction(arg= []):). Plusieurs appels à la fonction partageront et modifieront le même objet liste par défaut. Préférez None comme défaut et créez la liste à l'intérieur de la fonction si nécessaire.
  • Utilisation comme pile ou file : Les méthodes append() et pop() permettent d'utiliser une liste comme une pile (LIFO - Last-In, First-Out) avec des performances O(1). Pour une file (FIFO - First-In, First-Out), l'utilisation de pop(0) est inefifcace (O(n)). Il est préférable d'utiliser collections.deque pour des opérations de file performantes.
  • Consommation mémoire : Les listes Python stockent des références aux objets, chaque référence occupant une quantité fixe de mémoire (typiquement 8 octets sur un système 64 bits). Les objets eux-mêmes sont stockés ailleurs. Pour stocker de grandes quantités de données numériques de manière plus compacte, anvisagez les modules array ou les tableaux NumPy (numpy.ndarray).

Comparaison avec d'autres types

Type Mutabilité Restriction de type des éléments Cas d'usage typique
list Mutable Aucune Collections ordonnées générales, modifications fréquentes.
tuple Immuable Aucune Collections ordonnées fixes, utilisation comme clés de dictionnaire.
array.array Mutable Type numérique unique Stockage compact de données numériques, opérations de base.
numpy.ndarray Mutable Type numérique unique (ou objet) Calcul scientifique, opérations vectorielles et matricielles optimisées.

Étiquettes: Python liste structure de données mutable séquence

Publié le 5 août à 05h19