Listen sortieren, und die Methoden, die dazugehören
Was sorted() von .sort() unterscheidet, die Antworten, die max/min/sum/count/index geben, das Ändern der Sortierregel mit key= und das Verwandeln einer Liste mit join() in lesbaren Text.
Wie möchtest du lernen?
Das Problem, das wir lösen
Die Noten von sieben Leuten stehen in einer Liste. Drei Fragen wollen beantwortet sein: Was ist die höchste, was ist der Durchschnitt, und wer sind die besten drei?
Mit den Werkzeugen aus Kapitel zwölf sind die ersten beiden mit einer Schleife machbar — umständlich, aber möglich. Die dritte ist anders. „Die besten drei“ heißt, sie erst in Reihenfolge zu bringen, und dazu haben wir bisher keine Möglichkeit zu sortieren.
Diese Aufgaben kommen so oft vor, dass Python sie mitliefert. Das Kapitel von heute ist diese Liste von Werkzeugen — und eine Falle, in die fast jeder mindestens einmal tritt: Es gibt zwei Formen derselben Operation, eine, die die Liste verändert, und eine, die eine neue zurückgibt, und die falsche zu wählen wirft überhaupt keinen Fehler.
Am Ende dieses Kapitels kannst du
- Sagen, was
sorted()von.sort()unterscheidet, und welche Form jede Aufgabe braucht - Antworten aus einer Liste holen mit
max,min,sum,countundindex - Die Regel, die eine Sortierung nutzt, mit
key=ändern - Eine Liste in lesbaren Text verwandeln mit
join() - Erklären, warum das Sortieren einer Liste mit gemischten Typen einen
TypeErrorwirft
Voraussetzungen: Listen — viele Werte unter einem Namen.
sorted() und .sort() — das Herz dieses Kapitels
Beide sortieren. Der Unterschied ist, was zurückkommt.
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]Lies diese drei Ausgabezeilen genau durch.
sorted(marks) hat eine neue, sortierte Liste gebaut und zurückgegeben. Das Original marks bleibt unangetastet — die zweite Zeile ist der Beweis.
marks.sort() hat nichts gebaut. Es hat die Original-Liste sortiert, und die alte Reihenfolge ist endgültig weg.
Da ist die Regel aus Kapitel zwölf zurück: Eine Methode, die die Liste verändert, gibt nichts zurück.
marks = [72, 45, 90, 61]
marks = marks.sort()
print(marks)NoneGenau wie bei append. Bei .sort() darfst du das Ergebnis nicht aufbewahren; bei sorted() musst du es, sonst ist die Arbeit hingeworfen.
Was wann? Wenn die Original-Reihenfolge nicht mehr gebraucht wird, ist .sort() einfacher und günstiger. Wenn die Original-Liste woanders gebraucht wird, oder du dir nicht sicher bist, nimm sorted() — es nimmt niemandem etwas weg. Im Zweifel sorted().
Umgekehrte Reihenfolge und numerische Antworten
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 und sum sind Funktionen und keine Methoden, also max(marks) und nicht marks.max(). Für einen Durchschnitt gibt es nichts Besonderes: die Summe durch die Anzahl ist der Durchschnitt, und round(..., 2) kürzt ihn für die Anzeige.
Beachte, wie die akkumulierende Schleife aus Kapitel zehn zu einer einzigen Zeile geworden ist. Sie zu lernen war nicht umsonst — was sum tut, ist diese Schleife, und eines Tages wirst du etwas akkumulieren, wofür Python keine fertige Funktion hat.
Zählen und Finden
marks = [72, 45, 90, 45, 61]
print(marks.count(45))
print(marks.index(45))
print(marks.index(90))2
1
2count(x) sagt, wie oft x vorkommt. index(x) sagt, wo der erste davon steht — hat die Liste zwei 45, meldet es Index 1 und erwähnt die zweite nie.
Und nach etwas zu suchen, das nicht da ist, stoppt das Programm:
marks = [72, 45, 90]
print(marks.index(50))ValueError: 50 is not in listGenau wie remove. Gewöhne dir an, vorher mit if 50 in marks: zu prüfen.
Text sortieren und key=
names = ["rafi", "Bilal", "ahmed"]
print(sorted(names))
print(sorted(names, key=str.lower))['Bilal', 'ahmed', 'rafi']
['ahmed', 'Bilal', 'rafi']Die Leute sehen das erste Ergebnis und nehmen an, Python hätte es falsch gemacht. Hat es nicht — es sortiert nach Zeichencode, und dort steht jeder Großbuchstabe vor jedem Kleinbuchstaben. Also ist Bilal nach vorn gesprungen.
key=str.lower sagt: Behandle beim Sortieren jeden Namen, als wäre er klein geschrieben. Die Namen selbst bleiben unverändert — Bilal wird weiterhin mit großem B ausgegeben — nur der Vergleich nutzt die kleingeschriebene Form.
key kann jede beliebige Regel sein:
words = ["bag", "pen", "notebook", "ink"]
print(sorted(words, key=len))['bag', 'pen', 'ink', 'notebook']Sortiert nach Länge. Beachte, dass bag, pen und ink alle drei Zeichen lang sind und in der Reihenfolge geblieben sind, in der sie schon standen — Python lässt Gleichstände unangetastet. Diese Eigenschaft heißt stabiles Sortieren (stable sort), und sie macht Sortieren nach mehreren Kriterien möglich.
Gemischte Typen lassen sich nicht sortieren
values = [3, "1", 2]
print(sorted(values))TypeError: '<' not supported between instances of 'str' and 'int'Sortieren heißt, Dinge paarweise zu vergleichen, und Kapitel acht hat gezeigt, dass eine Zahl und ein Stück Text sich nicht mit < vergleichen lassen. Die Meldung ist Wort für Wort dieselbe. Das passiert regelmäßig bei Listen, die aus einer CSV-Datei gelesen werden, wo jede Zahl eigentlich Text ist.
Von einer Liste zu Text — join
Eine Liste direkt auszugeben liefert Klammern und Anführungszeichen, und das ist nichts, was man einem Menschen zeigt:
names = ["rafi", "ahmed", "bilal"]
print(", ".join(names))
print(" | ".join(names))rafi, ahmed, bilal
rafi | ahmed | bilalDie Zeile liest sich beim ersten Mal rückwärts: der verbindende Text kommt zuerst, und die Liste steht in den Klammern. Die Eselsbrücke — „verbinde diese mit diesem“.
Es gibt eine Bedingung, und sie ist streng: Jeder Wert muss Text sein.
marks = [72, 45, 90]
print(", ".join(marks))TypeError: sequence item 0: expected str instance, int foundUm eine Liste von Zahlen zu verbinden, machst du jede zuerst zu Text:
marks = [72, 45, 90]
print(", ".join(str(m) for m in marks))72, 45, 90Der Teil str(m) for m in marks ist neu, und ein späteres Kapitel bringt ihn vollständig bei. Lies ihn vorerst so: „für jedes m in marks, mach str(m).“ Dann verbindet join diese Strings. Das vollständige Beispiel unten benutzt dieselbe Zeile.
Ein vollständiges Beispiel
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 7Zwei Designentscheidungen lohnen einen Blick.
sorted() wurde statt .sort() gewählt, weil das Original marks in der ersten Zeile noch einmal ausgegeben wird. Mit .sort() hätten die Zeilen „Marks“ und „Ordered“ dasselbe gezeigt, und niemand hätte sich beschwert. Das ist genau der stille Fehler, mit dem dieses Kapitel begonnen hat.
Die besten drei kamen aus einem Slice — ordered[:3]. Es war keine eigene Funktion für „die besten drei“ nötig: Die ersten drei einer absteigenden Liste sind die besten drei. Ist etwas sortiert, werden überraschend viele Fragen zu einem einzigen Slice.
Wenn etwas schiefgeht
Meine Liste wurde nach dem Sortieren None Die Zeile lautete marks = marks.sort(). .sort() sortiert die Liste selbst und gibt None zurück — schreib einfach marks.sort(). Für eine neue Liste: ordered = sorted(marks).
Das Sortieren hat auch die Original-Liste verändert Du hast .sort() benutzt, das an Ort und Stelle sortiert. Nutze sorted(), um das Original unangetastet zu lassen.
TypeError: '<' not supported between instances of 'str' and 'int' Die Liste mischt Zahlen und Text. Führe print(marks) aus und schau, welche Werte in Anführungszeichen stehen; wenn sie aus einer Datei stammen, sind sie wahrscheinlich alle Text und brauchen int().
ValueError: 50 is not in list index() oder remove() wurde ein Wert gegeben, den die Liste nicht enthält. Prüfe vorher mit in.
TypeError: sequence item 0: expected str instance, int found join() wurde eine Liste von Zahlen übergeben. Packe jede in str().
Nach dem Sortieren von Namen kamen alle Großgeschriebenen zuerst Das ist korrektes Verhalten, kein Bug. Um so zu sortieren, wie es ein Mensch erwartet: sorted(names, key=str.lower).
Schritt 4 von 6 — Vorhersagen
Prüfe dein Verständnis
sorted() wurde benutzt. Was geben die beiden Zeilen aus?
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]
Das Ergebnis von .sort() wird wieder in marks gespeichert. Was wird ausgegeben?
marks = [72, 45, 90]
marks = marks.sort()
print(marks)- AEin `AttributeError`
- B[72, 45, 90]
- C[45, 72, 90]
- DNone
Ein Versuch, eine Liste von Zahlen mit Kommas zu verbinden. Was passiert?
marks = [72, 45, 90]
print(", ".join(marks))- AEin `TypeError` — `join` kann nur Text verbinden
- B724590
- C72, 45, 90
- D[72, 45, 90]
Zum Antworten brauchst du ein Konto
Melde dich an, um deine Antworten zu prüfen
Die Fragen stehen oben, und sie im Kopf durchzuarbeiten ist der wichtige Teil. Melde dich an, um die Antworten, die Erklärungen und die dreistufigen Hinweise zu sehen.
Jetzt bist du dran
Schreib eine Datei namens inventory.py, die eine Liste von mindestens sieben Produktnamen und eine Liste ihrer Preise enthält.
Gib aus den Preisen Folgendes aus:
- Die höchste, die niedrigste, die Summe und den Durchschnitt (auf zwei Stellen)
- Eine neue sortierte Liste — und beweise dann, dass das Original unverändert ist
- Die drei teuersten, mit einem Slice
Gib aus den Namen Folgendes aus:
- Alphabetische Reihenfolge, ohne Groß-/Kleinschreibung
- Sortiert nach der Länge des Namens
- Alle Namen in einer Zeile, durch Kommas getrennt, mit
join
Führ dann ein Experiment durch: Rufe .sort() für die Preise auf und gib die Zeilen aus Teil 1 noch einmal aus. Welche Zahlen haben sich geändert und welche nicht? Erkläre dir selbst, warum die, die sich nicht geändert haben, sich nicht ändern konnten — behalte diese Antwort, und die Falle dieses Kapitels wird dich nie erwischen.
Schritt 6 von 6
Herausforderung — das Kapitel-Quiz
Zehn Fragen von leicht bis schwer. Die letzten sind absichtlich knifflig.
Melde dich an, um das Quiz zu machen