ProgrammationDéveloppeur Python

Décrivez les principes de fonctionnement des gestionnaires de mémoire dans les listes et les tuples en Python. Quelle est la différence entre la modification/l'ajout d'éléments dans une liste et un tuple, et comment cela affecte-t-il les performances ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

En Python, les listes (list) sont des structures modifiables, tandis que les tuples (tuple) sont immuables.

  • list : Lors de l'ajout de nouveaux éléments (append, extend, insert), Python réserve des blocs de mémoire "avec surplus" pour minimiser le nombre d'allocations lors de la croissance du tableau (stratégie de "sur-allocation"). La suppression d'éléments (pop, remove) est rapide, mais peut parfois entraîner une redistribution de la mémoire.
  • tuple : La taille d'un tuple est constante, les éléments ne peuvent pas être modifiés ou ajoutés — cela assure une vitesse élevée pour les opérations de lecture et une consommation de mémoire plus faible par rapport aux listes lors du stockage d'un grand nombre de données immuables.

Exemple illustrant la modification d'une liste et d'un tuple :

lst = [1, 2, 3] lst.append(4) # OK lst[1] = 20 # OK tup = (1, 2, 3) tup[1] = 20 # TypeError

Performances :

  • Les listes conviennent bien aux collections souvent modifiées.
  • Les tuples sont légèrement plus rapides, plus optimaux en mémoire (en raison de leur taille constante et de leurs principes de hachage), et sont appropriés pour être utilisés comme clés dans des dictionnaires ou pour des valeurs de retour de fonctions (données immuables).

Question piège

Question : Pourquoi les opérations d'ajout d'éléments à une liste sont-elles généralement rapides (O(1)), alors que du point de vue d'un tableau elles devraient entraîner une redistribution de la mémoire ?

Réponse :

Python implémente des tableaux dynamiques avec "réservation de mémoire excédentaire" dès lors que plusieurs éléments sont ajoutés. Ainsi, append prend généralement O(1), et la redistribution de la mémoire se produit uniquement lorsque le bloc de réserve est réellement épuisé.

Exemple :

import sys lst = [] for i in range(10): lst.append(i) print(len(lst), sys.getsizeof(lst)) # La taille de la mémoire augmente de manière non strictement linéaire

Historique

Exemple 1

Dans un projet, list a été utilisé pour les clés du dictionnaire. Le développeur ne savait pas que les listes ne peuvent pas être hachées (mutabilité), ce qui a entraîné l'erreur "TypeError: unhashable type: 'list'".


Exemple 2

Le développeur créait souvent de longues listes en les concaténant via +. Cela entraînait des copies supplémentaires de tableaux et des surcoûts élevés en mémoire et en temps. Il était plus efficace d'utiliser append dans une boucle ou des générateurs.


Exemple 3

Dans un système de journalisation, des tuples ont été choisis pour stocker des horodatages, pensant qu'en raison de leur immutabilité, cela serait plus rapide. Mais la nécessité de modifications occasionnelles entraînait constamment la création de nouveaux tuples (copie à l'écriture) et ralentissait les performances par rapport à l'utilisation de listes.