Trier des listes, et les méthodes qui vont avec
Ce qui sépare sorted() de .sort(), les réponses que donnent max/min/sum/count/index, changer la règle avec key=, et transformer une liste en texte lisible avec join().
Comment voulez-vous apprendre ?
Le problème que nous résolvons
Les notes de sept personnes sont dans une liste. Trois questions attendent une réponse : quelle est la plus élevée, quelle est la moyenne, et qui sont les trois premiers ?
Avec les outils du chapitre douze, les deux premières peuvent se faire avec une boucle — laborieusement, mais c'est possible. La troisième est différente. « Les trois premiers » suppose d'abord de les mettre dans l'ordre, et nous n'avons encore aucun moyen de trier quoi que ce soit.
Ces tâches reviennent si souvent que Python les fournit d'office. Le chapitre d'aujourd'hui est cette liste d'outils — et un piège dans lequel presque tout le monde tombe au moins une fois : il existe deux formes de la même opération, une qui change la liste et une autre qui en renvoie une nouvelle, et choisir la mauvaise ne lève aucune erreur.
À la fin de ce chapitre, vous pourrez
- Dire ce qui sépare
sorted()de.sort(), et laquelle chaque tâche réclame - Extraire des réponses d'une liste avec
max,min,sum,countetindex - Changer la règle qu'utilise un tri avec
key= - Transformer une liste en texte lisible avec
join() - Expliquer pourquoi trier une liste de types mixtes lève un
TypeError
Prérequis : Les listes — beaucoup de valeurs sous un seul nom.
sorted() et .sort() — le cœur de ce chapitre
Les deux trient. La différence, c'est ce qui est renvoyé.
marks = [72, 45, 90, 61]
ordered = sorted(marks)
print(ordered)
print(marks)
marks.sort()
print(marks)[45, 61, 72, 90]
[72, 45, 90, 61]
[45, 61, 72, 90]Lisez attentivement ces trois lignes de sortie.
sorted(marks) a construit une nouvelle liste triée et vous l'a rendue. L'original marks est intact — la deuxième ligne en est la preuve.
marks.sort() n'a rien construit. Elle a trié la liste originale, et l'ancien ordre a disparu pour de bon.
C'est la règle du chapitre douze qui revient : une méthode qui modifie la liste ne renvoie rien.
marks = [72, 45, 90, 61]
marks = marks.sort()
print(marks)NoneExactement comme append. Avec .sort(), vous ne devez pas conserver le résultat ; avec sorted(), vous devez le faire, sinon le travail est jeté.
Laquelle, et quand ? Si l'ordre original n'est plus nécessaire, .sort() est plus simple et plus économique. Si la liste originale sert ailleurs, ou si vous n'êtes pas sûr, utilisez sorted() — elle n'enlève rien à personne. En cas de doute, sorted().
Ordre inversé, et réponses numériques
marks = [72, 45, 90, 61]
print(sorted(marks, reverse=True))
print(max(marks), min(marks), sum(marks))
print(round(sum(marks) / len(marks), 2))[90, 72, 61, 45]
90 45 268
67.0max, min et sum sont des fonctions plutôt que des méthodes, donc on écrit max(marks) et non marks.max(). Il n'y a rien de spécial pour une moyenne : le total divisé par le nombre est la moyenne, et round(..., 2) l'arrondit pour l'affichage.
Remarquez que la boucle d'accumulation du chapitre dix s'est résumée en une ligne. L'avoir apprise n'a pas été vain — ce que fait sum est cette boucle, et un jour vous devrez accumuler quelque chose pour lequel Python n'a pas de fonction toute prête.
Compter et trouver
marks = [72, 45, 90, 45, 61]
print(marks.count(45))
print(marks.index(45))
print(marks.index(90))2
1
2count(x) indique combien de fois x apparaît. index(x) indique où se trouve le premier — avec deux 45, il donne l'index 1 et ne mentionne jamais le second.
Et chercher quelque chose qui n'est pas là arrête le programme :
marks = [72, 45, 90]
print(marks.index(50))ValueError: 50 is not in listTout comme remove. Prenez l'habitude de vérifier d'abord avec if 50 in marks:.
Trier du texte, et key=
names = ["rafi", "Bilal", "ahmed"]
print(sorted(names))
print(sorted(names, key=str.lower))['Bilal', 'ahmed', 'rafi']
['ahmed', 'Bilal', 'rafi']On voit le premier résultat et on suppose que Python s'est trompé. Ce n'est pas le cas — il trie par code de caractère, et là, chaque lettre majuscule vient avant chaque lettre minuscule. C'est pourquoi Bilal est passé en tête.
key=str.lower dit : lors du tri, traiter chaque nom comme s'il était en minuscules. Les noms eux-mêmes sont inchangés — Bilal s'affiche toujours avec son B majuscule — seule la comparaison utilise la forme en minuscules.
key peut être n'importe quelle règle :
words = ["bag", "pen", "notebook", "ink"]
print(sorted(words, key=len))['bag', 'pen', 'ink', 'notebook']Trié par longueur. Remarquez que bag, pen et ink font tous trois caractères et sont restés dans l'ordre où ils étaient déjà — Python ne bouscule pas les égalités. Cette propriété s'appelle un tri stable, et c'est elle qui rend possible le tri selon plusieurs critères.
Les types mixtes ne peuvent pas être triés
values = [3, "1", 2]
print(sorted(values))TypeError: '<' not supported between instances of 'str' and 'int'Trier, c'est comparer les choses deux par deux, et le chapitre huit a montré qu'un nombre et un morceau de texte ne peuvent pas être comparés avec <. Le message est mot pour mot le même. Cela arrive couramment avec des listes lues depuis un fichier CSV, où chaque nombre est en réalité du texte.
D'une liste au texte — join
Afficher directement une liste vous donne des crochets et des guillemets, ce qui n'est pas fait pour être montré à une personne :
names = ["rafi", "ahmed", "bilal"]
print(", ".join(names))
print(" | ".join(names))rafi, ahmed, bilal
rafi | ahmed | bilalLa ligne se lit à l'envers la première fois : le texte de liaison vient en premier, et la liste va dans les crochets. La façon de s'en souvenir — « joindre ceci avec cela ».
Il y a une condition, et elle est stricte : chaque valeur doit être du texte.
marks = [72, 45, 90]
print(", ".join(marks))TypeError: sequence item 0: expected str instance, int foundPour joindre une liste de nombres, transformez d'abord chacun en texte :
marks = [72, 45, 90]
print(", ".join(str(m) for m in marks))72, 45, 90La partie str(m) for m in marks est nouvelle, et un chapitre plus loin l'enseigne en entier. Pour l'instant, lisez-la ainsi : « pour chaque m dans marks, faire str(m) ». Ensuite, join joint ces chaînes. L'exemple complet ci-dessous utilise la même ligne.
Un exemple complet
report.py :
# A marks report: order them, summarise them, and show the top three
marks = [72, 45, 90, 61, 88, 45, 33]
ordered = sorted(marks, reverse=True)
print("Marks :", marks)
print("Ordered :", ordered)
print("Count :", len(marks))
print("Highest :", max(marks))
print("Lowest :", min(marks))
print("Total :", sum(marks))
print("Average :", round(sum(marks) / len(marks), 2))
print("How many 45s:", marks.count(45))
top_three = ordered[:3]
print("Top three:", top_three)
print("As text :", ", ".join(str(m) for m in top_three))
passed = []
for mark in marks:
if mark >= 40:
passed.append(mark)
print("Passed :", len(passed), "of", len(marks))Marks : [72, 45, 90, 61, 88, 45, 33]
Ordered : [90, 88, 72, 61, 45, 45, 33]
Count : 7
Highest : 90
Lowest : 33
Total : 434
Average : 62.0
How many 45s: 2
Top three: [90, 88, 72]
As text : 90, 88, 72
Passed : 6 of 7Deux décisions de conception méritent qu'on les remarque.
sorted() a été choisi plutôt que .sort() parce que l'original marks est affiché à nouveau sur la première ligne. Avec .sort(), les lignes « Marks » et « Ordered » auraient montré la même chose et rien ne se serait plaint. C'est précisément l'erreur silencieuse avec laquelle ce chapitre a commencé.
Les trois premiers sont sortis d'un slice — ordered[:3]. Aucune fonction séparée pour les « trois premiers » n'était nécessaire : les trois premiers d'une liste décroissante sont les trois premiers. Une fois quelque chose trié, un nombre étonnant de questions deviennent un slice.
En cas de problème
Ma liste est devenue None après l'avoir triée La ligne disait marks = marks.sort(). .sort() trie la liste elle-même et renvoie None — écrivez simplement marks.sort(). Pour une nouvelle liste, ordered = sorted(marks).
Le tri a aussi changé la liste originale Vous avez utilisé .sort(), qui trie sur place. Utilisez sorted() pour laisser l'original tranquille.
TypeError: '<' not supported between instances of 'str' and 'int' La liste mélange des nombres et du texte. Lancez print(marks) et voyez quelles valeurs ont des guillemets autour ; si elles viennent d'un fichier, elles sont probablement toutes du texte, et ont besoin de int().
ValueError: 50 is not in list index() ou remove() a reçu une valeur que la liste ne contient pas. Vérifiez d'abord avec in.
TypeError: sequence item 0: expected str instance, int found join() a reçu une liste de nombres. Convertissez chacune avec str().
Après avoir trié des noms, tous ceux avec une majuscule sont venus en premier C'est un comportement correct, pas un bug. Pour trier comme une personne s'y attend, sorted(names, key=str.lower).
Étape 4 sur 6 — Prédire
Vérifiez votre compréhension
sorted() a été utilisé. Que s'affichent les deux lignes ?
marks = [72, 45, 90]
ordered = sorted(marks)
print(ordered)
print(marks)- A[45, 72, 90] [72, 45, 90]
- B[45, 72, 90] None
- C[45, 72, 90] [45, 72, 90]
- D[72, 45, 90] [45, 72, 90]
Le résultat de .sort() est réassigné à marks. Que s'affiche-t-il ?
marks = [72, 45, 90]
marks = marks.sort()
print(marks)- AUne `AttributeError`
- B[72, 45, 90]
- C[45, 72, 90]
- DNone
Une tentative de joindre une liste de nombres avec des virgules. Que se passe-t-il ?
marks = [72, 45, 90]
print(", ".join(marks))- AUn `TypeError` — `join` ne peut joindre que du texte
- B724590
- C72, 45, 90
- D[72, 45, 90]
Répondre nécessite un compte
Connectez-vous pour vérifier vos réponses
Les questions sont ci-dessus, et les résoudre de tête est ce qui compte vraiment. Connectez-vous pour voir les réponses, les explications et les indices à trois niveaux.
À vous de jouer
Écrivez un fichier appelé inventory.py contenant une liste d'au moins sept noms de produits et une liste de leurs prix.
À partir des prix, affichez :
- Le plus haut, le plus bas, le total et la moyenne (à deux décimales)
- Une nouvelle liste triée — puis prouvez que l'original est inchangé
- Les trois plus chers, avec un slice
À partir des noms, affichez :
- L'ordre alphabétique, en ignorant les majuscules
- Triés par la longueur du nom
- Tous les noms sur une ligne, séparés par des virgules, avec
join
Puis lancez une expérience : appelez .sort() sur les prix, et affichez à nouveau les lignes de la partie 1. Quels nombres ont changé et lesquels non ? Expliquez-vous pourquoi ceux qui n'ont pas changé n'auraient pas pu changer — gardez cette réponse et le piège de ce chapitre ne vous prendra jamais.
Étape 6 sur 6
Défi — le quiz du chapitre
Dix questions, de la plus facile à la plus difficile. Les dernières sont difficiles exprès.
Connectez-vous pour faire le quiz