Le tri des données revient partout en Python: listes de notes, noms d’utilisateurs, résultats d’API, événements de log. Ici, je montre comment exploiter la fonction `sort` de Python sans confusion, quand préférer `sorted()`, comment piloter l’ordre avec `key` et `reverse`, et quels pièges évitent les bugs les plus agaçants.
Les points essentiels à retenir avant de trier une liste
- `list.sort()` trie en place et renvoie `None`.
- `sorted()` renvoie une nouvelle liste et laisse l’original intact.
- `key` sert à définir le critère réel de tri, pas seulement l’ordre naturel des valeurs.
- `reverse=True` inverse l’ordre sans casser la stabilité du tri.
- Le tri Python est stable : deux éléments égaux gardent leur ordre initial.
- Un tri peut échouer si les éléments ne sont pas comparables entre eux ou si la clé est mal pensée.
Comment fonctionne le tri en Python
Quand je parle de tri en Python, je distingue toujours deux outils. D’un côté, la méthode list.sort(), qui agit directement sur une liste existante. De l’autre, la fonction sorted(), qui prend n’importe quel itérable et retourne une nouvelle liste triée. Cette nuance change beaucoup de choses dans un code réel, surtout dès qu’on travaille avec des données venant d’une API, d’un CSV ou d’un objet métier.
Le point que beaucoup de débutants ratent, c’est que sort() ne renvoie pas la liste triée. Elle modifie la liste d’origine et renvoie None. C’est volontaire: Python veut signaler clairement qu’on a choisi une opération avec effet de bord. Si vous écrivez result = ma_liste.sort(), result vaudra None, pas la liste triée.
Le tri accepte aussi deux paramètres majeurs: key et reverse. Le premier sert à extraire la valeur sur laquelle comparer chaque élément. Le second inverse l’ordre. En pratique, c’est souvent key qui fait tout le travail utile, car il permet de trier selon une note, un nom normalisé, une date, un champ d’objet ou un attribut calculé. La vraie question devient alors: sur quel critère voulez-vous classer les données? C’est précisément ce qui mène au choix entre tri en place et tri sur copie.

Choisir entre `sort()` et `sorted()` selon le contexte
Je recommande de choisir l’outil en fonction de ce que vous voulez préserver. Si la liste d’origine n’a plus d’importance, sort() est simple et économe. Si vous devez garder la version brute pour un affichage, un audit ou un traitement ultérieur, sorted() est plus sûr.
| Situation | Meilleur choix | Pourquoi |
|---|---|---|
| Je veux modifier la liste existante | sort() |
Le tri se fait en place, sans créer une seconde liste. |
| Je veux conserver l’ordre d’origine | sorted() |
La liste source reste intacte, ce qui évite des effets de bord. |
| Je travaille sur un tuple, un set ou un générateur | sorted() |
sort() n’existe que pour les listes. |
| Je trie une très grosse structure | sort() |
Pas de copie complète à allouer, donc un usage mémoire plus sobre. |
En pratique, je pars souvent de cette règle simple: si je ne suis pas certain de pouvoir écraser la donnée d’origine, j’utilise `sorted()`. C’est plus robuste dans un pipeline de données, un service web ou un script de nettoyage. Une fois cette décision prise, il reste à définir le bon critère de tri, et c’est là que key devient indispensable.
Utiliser `key` pour trier selon ce qui compte vraiment
Un tri naturel n’est pas toujours le bon tri. Trier des chaînes par ordre alphabétique brut, des dictionnaires par note, ou des objets par date ne demande pas la même logique. Le paramètre key permet de dire à Python ce qu’il doit réellement comparer. Je trouve que c’est le point le plus important à maîtriser, parce qu’il transforme un tri banal en outil de traitement précis.
Voici un premier cas très classique avec des chaînes:
mots = ["Banane", "abricot", "cerise", "Éclair"]
mots_tries = sorted(mots, key=str.lower)
Ici, str.lower neutralise la casse. Sans cela, les majuscules peuvent perturber l’ordre attendu. C’est utile pour des menus, des annuaires ou des résultats de recherche affichés à l’utilisateur.
Avec des dictionnaires, on utilise souvent une fonction anonyme:
etudiants = [
{"prenom": "Élise", "note": 16},
{"prenom": "Mehdi", "note": 12},
{"prenom": "Zoé", "note": 16},
]
etudiants.sort(key=lambda e: e["note"], reverse=True)
Le tri se fait ici par note décroissante. Comme le tri Python est stable, Élise restera devant Zoé si elles ont la même note et si cet ordre existait déjà dans la liste. Ce détail compte beaucoup quand on enchaîne plusieurs tris ou quand on veut conserver une logique d’affichage cohérente.
Pour des données plus structurées, trier sur un tuple est souvent plus lisible qu’empiler des conditions:
evenements = [
("reseau", 2),
("reseau", 1),
("ia", 3),
("ia", 1),
]
evenements.sort(key=lambda x: (x[0], x[1]))
Le tuple de clé est comparé de gauche à droite. C’est propre, prévisible et très pratique pour des datasets, des journaux applicatifs ou des exports métiers. Quand on comprend cette logique, on commence à écrire des tris qui reflètent vraiment le besoin fonctionnel au lieu de simplement classer des valeurs.
Trier à l’envers sans perdre un ordre cohérent
Le paramètre reverse=True inverse l’ordre sans obliger à bricoler la clé de tri. Je préfère cette option à des astuces du style multiplier par -1 partout, parce qu’elle reste lisible et garde le code explicite. C’est particulièrement net quand on trie des scores, des timestamps ou des classements.
scores = [
{"joueur": "Ana", "points": 48},
{"joueur": "Luca", "points": 62},
{"joueur": "Nora", "points": 62},
]
scores.sort(key=lambda s: s["points"], reverse=True)
Le résultat est décroissant, mais la stabilité du tri reste intacte. Cela veut dire que si Luca et Nora ont le même score, leur ordre initial est conservé. Dans un tableau de bord, une page de résultats ou une interface d’administration, cette stabilité donne un comportement plus prévisible et moins frustrant pour l’utilisateur.
Si vous devez trier plusieurs fois sur des critères différents, vous pouvez aussi enchaîner les opérations en tirant parti de cette stabilité. Par exemple, trier d’abord par catégorie, puis par score, fonctionne correctement si vous gardez en tête l’ordre des passes. Cette approche est souvent plus claire qu’un gros `lambda` illisible, surtout quand les règles métiers commencent à se multiplier.
Les erreurs que je vois le plus souvent avec le tri
Les bugs de tri sont rarement spectaculaires, mais ils coûtent du temps parce qu’ils donnent des résultats “presque bons”. Je conseille de surveiller quelques pièges récurrents.
-
Confondre retour et effet de bord :
sort()modifie la liste et renvoieNone. - Essayer de trier des types incompatibles : mélanger des chaînes, des nombres et des valeurs non ordonnées peut faire échouer le tri.
- Muter la liste pendant le tri : Python ne garantit rien dans ce cas, et la liste peut se retrouver dans un état partiellement modifié.
- Négliger la langue ou la locale : un tri de chaînes brut n’est pas toujours un tri linguistique français au sens attendu.
- Écrire une clé coûteuse sans raison : la fonction de clé est appelée une fois par élément, donc autant la garder simple et déterministe.
Sur le dernier point, je suis prudent avec les traitements “intelligents” dans key. Si la clé fait trop de calculs, vous ralentissez tout le tri. Et si elle dépend d’un état externe, vous rendez le résultat plus fragile. Dans un script de production, je privilégie presque toujours une clé claire, testable et stable plutôt qu’une astuce élégante mais difficile à relire.
Pour des noms ou des libellés en français, je vérifie aussi le comportement réel sur un petit échantillon de données avec accents, majuscules et tirets. Le tri standard de Python compare les chaînes selon leur ordre Unicode; cela suffit souvent, mais pas toujours si vous attendez un ordre linguistique strict. C’est précisément le genre de détail qui change la qualité perçue d’un outil.
Ma règle simple pour écrire un tri fiable en production
Si je dois retenir une seule méthode de travail, c’est celle-ci: je commence par décider si je veux modifier la liste ou en produire une nouvelle. Ensuite, je formule la vraie clé métier du tri, pas juste la colonne la plus visible. Enfin, je teste le résultat avec des données qui contiennent des cas limites: doublons, casse différente, valeurs nulles, caractères accentués et ordres inattendus.
Dans la plupart des projets, cette discipline suffit à éviter 90 % des problèmes liés au tri. Elle rend le code plus lisible, les résultats plus prévisibles et les évolutions plus simples à gérer. Si vous retenez une seule chose de cet article, gardez celle-ci: un bon tri en Python ne consiste pas à “mettre dans l’ordre”, mais à choisir précisément l’ordre qui sert la donnée et l’utilisateur.