Python liste append : bonnes pratiques pour un code plus propre

La méthode append() modifie la liste en place et renvoie None. Écrire ma_liste = ma_liste.append(x) écrase la référence avec None et provoque un bug silencieux. Ce piège reste la première source d’erreurs chez les développeurs qui passent d’un langage fonctionnel à Python. Nous partons de ce constat pour poser les règles d’un usage propre de append sur une liste Python, puis identifier les cas où cette méthode n’est pas le bon choix.

Mutation en place et valeur de retour : le piège fondamental de append

En Python, les méthodes qui modifient un objet mutable (listes, sets, dictionnaires) suivent une convention de design : elles renvoient None pour signaler qu’elles agissent par effet de bord. append() respecte cette convention.

Le problème survient dans le chaînage ou l’assignation :

resultat = ma_liste.append(42) produit resultat = None tandis que ma_liste contient bien le nouvel élément. Dans une boucle, cette erreur passe inaperçue jusqu’à ce qu’on tente d’itérer sur resultat.

La règle est simple : ne jamais capturer la valeur de retour de append(). Si vous avez besoin d’une nouvelle liste enrichie sans toucher l’originale, utilisez la concaténation (nouvelle = ancienne + [element]) ou une compréhension de liste. Ce choix n’est pas qu’une question de style, il traduit une intention : mutation ou création.

Quand remplacer append par une compréhension de liste Python

Jeune femme codant en Python avec des listes et la méthode append sur un canapé dans un salon moderne

Nous recommandons un test direct : si la boucle ne contient qu’un append() précédé d’un if ou d’une transformation simple, une compréhension de liste produit un code plus court et plus lisible.

Comparons deux patterns :

resultats = []
for x in donnees:
  if x > 0:
    resultats.append(x * 2)

Devient :

resultats = [x * 2 for x in donnees if x > 0]

La compréhension de liste remplace append quand la logique tient en une expression. En revanche, dès que la boucle contient une logique métier complexe (try/except, appels externes, mises à jour d’état), append() explicite reste préférable. Forcer une compréhension de liste sur plusieurs lignes avec des conditions imbriquées dégrade la lisibilité au lieu de l’améliorer.

Le cas des compréhensions imbriquées

Une double compréhension ([f(x) for sous_liste in matrice for x in sous_liste]) reste acceptable si le lecteur comprend l’aplatissement en une seconde. Au-delà de deux niveaux, nous passons systématiquement à une boucle avec append(), quitte à perdre la compacité.

append, extend et insert : choisir selon l’intention du code Python

L’erreur classique consiste à utiliser append() pour ajouter les éléments d’un itérable. Le résultat est une liste imbriquée au lieu d’une liste plate :

ma_liste.append([4, 5, 6]) insère la sous-liste comme un seul élément. ma_liste.extend([4, 5, 6]) ajoute chaque élément individuellement.

La règle de choix tient en trois points :

  • append() pour un seul élément : un entier, une chaîne, un objet. L’intention est « j’ajoute une chose à la fin »
  • extend() pour fusionner un itérable dans la liste existante. L’intention est « je concatène deux séquences »
  • insert(index, element) uniquement quand la position compte. Sur de grandes listes, chaque appel à insert(0, ...) décale tous les éléments existants, ce qui dégrade la performance de manière significative en cas d’appels répétés

Si vous faites des insertions fréquentes en tête de liste, collections.deque avec appendleft() est l’alternative performante. Le deque offre une insertion en temps constant aux deux extrémités, là où insert(0, ...) sur une liste standard a un coût proportionnel à la taille de la liste.

Patterns à éviter avec append en boucle Python

Deux ingénieurs logiciels discutant d'un script Python utilisant append dans un bureau tech en open space

Certains usages de append() signalent un code qui gagnerait à être restructuré.

Construire un dictionnaire avec append

Accumuler des paires clé-valeur dans une liste de tuples via append() pour ensuite convertir en dictionnaire est un détour. Utilisez directement une compréhension de dictionnaire ({k: v for k, v in source}) ou alimentez le dictionnaire avec dict[cle] = valeur dans la boucle.

Concaténation de chaînes via une liste

Le pattern morceaux.append(s) suivi de "".join(morceaux) reste valide pour assembler un grand nombre de fragments de texte. En revanche, si vous n’ajoutez que deux ou trois éléments, une f-string est plus directe et plus lisible.

Append dans une boucle sans condition

Si chaque itération ajoute systématiquement un élément transformé, c’est le signal d’une compréhension de liste. Un append sans if dans une boucle for est presque toujours remplaçable par [transform(x) for x in iterable].

Liste Python et structures alternatives : au-delà de append

La liste n’est pas toujours la bonne structure. Nous observons que le réflexe liste + append persiste même quand le besoin ne correspond pas à une collection ordonnée et redimensionnable.

  • Pour une pile (LIFO), la liste fonctionne bien avec append() et pop(). Pour une file (FIFO), préférez collections.deque avec append() et popleft()
  • Pour des données homogènes de taille fixe destinées à du calcul numérique, array.array ou un tableau NumPy consomme moins de mémoire et offre des opérations vectorisées
  • Pour un ensemble d’éléments uniques, un set avec add() élimine les doublons sans vérification manuelle

Le choix de la structure de données conditionne la propreté du code autant que le choix de la méthode d’ajout. Un append() suivi d’un test d’unicité est un signal pour passer à un set.

Garder un code lisible avec les listes Python passe moins par la maîtrise de append() que par la capacité à reconnaître quand il ne faut pas l’utiliser. Compréhension de liste pour les transformations simples, extend() pour les fusions, deque pour les insertions en tête, set pour l’unicité : chaque outil a son périmètre. Le meilleur append est parfois celui qu’on n’écrit pas.

Toute l'actu