Ordinare le liste, e i metodi che le accompagnano
Cosa distingue sorted() da .sort(), le risposte che danno max/min/sum/count/index, cambiare la regola con key=, e trasformare una lista in testo leggibile con join().
Come vuoi imparare?
Il problema che stiamo risolvendo
I voti di sette persone sono in una lista. Tre domande a cui rispondere: qual è il più alto, qual è la media, e quali sono i primi tre?
Con gli strumenti del capitolo dodici le prime due si possono fare con un ciclo — laborioso, ma possibile. La terza è diversa. "I primi tre" significa prima metterli in ordine, e non abbiamo ancora modo di ordinare niente.
Questi lavori ricorrono così spesso che Python li include già. Il capitolo di oggi è quell'elenco di strumenti — e una trappola in cui quasi tutti inciampano almeno una volta: ci sono due forme della stessa operazione, una che cambia la lista e una che ne restituisce una nuova, e scegliere quella sbagliata non solleva alcun errore.
Alla fine di questo capitolo sarai in grado di
- Dire cosa distingue
sorted()da.sort(), e quale dei due serve a ogni lavoro - Ottenere risposte da una lista con
max,min,sum,counteindex - Cambiare la regola che un ordinamento usa con
key= - Trasformare una lista in testo leggibile con
join() - Spiegare perché ordinare una lista di tipi misti solleva un
TypeError
Prerequisiti: Liste — molti valori sotto un solo nome.
sorted() e .sort() — il cuore di questo capitolo
Entrambi ordinano. La differenza è ciò che restituiscono.
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]Leggi con attenzione quelle tre righe di output.
sorted(marks) ha costruito una nuova lista ordinata e te l'ha restituita. L'marks originale non è toccato — la seconda riga è la prova.
marks.sort() non ha costruito niente. Ha ordinato la lista originale, e il vecchio ordine è sparito per sempre.
È la regola del capitolo dodici che torna: un metodo che modifica la lista non restituisce niente.
marks = [72, 45, 90, 61]
marks = marks.sort()
print(marks)NoneEsattamente come append. Con .sort() non devi conservare il risultato; con sorted() devi farlo, o il lavoro va perso.
Quale, e quando? Se l'ordine originale non serve più, .sort() è più semplice e più economico. Se la lista originale serve altrove, o non ne sei sicuro, usa sorted() — non toglie niente a nessuno. In caso di dubbio, sorted().
Ordine inverso e risposte numeriche
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 e sum sono funzioni e non metodi, quindi si scrive max(marks) e non marks.max(). Non c'è niente di speciale per la media: il totale diviso per il conteggio è la media, e round(..., 2) la accorcia per la visualizzazione.
Nota che il ciclo di accumulo del capitolo dieci è diventato una sola riga. Impararlo non è stato sprecato — ciò che fa sum è quel ciclo, e un giorno dovrai accumulare qualcosa per cui Python non ha una funzione pronta.
Contare e cercare
marks = [72, 45, 90, 45, 61]
print(marks.count(45))
print(marks.index(45))
print(marks.index(90))2
1
2count(x) dice quante volte appare x. index(x) dice dove si trova il primo — con due 45 indica l'indice 1 e non menziona mai il secondo.
E cercare qualcosa che non c'è ferma il programma:
marks = [72, 45, 90]
print(marks.index(50))ValueError: 50 is not in listEsattamente come remove. Abituati a controllare prima con if 50 in marks:.
Ordinare il testo, e key=
names = ["rafi", "Bilal", "ahmed"]
print(sorted(names))
print(sorted(names, key=str.lower))['Bilal', 'ahmed', 'rafi']
['ahmed', 'Bilal', 'rafi']Le persone vedono il primo risultato e pensano che Python abbia sbagliato. Non è così — ordina per codice del carattere, e lì ogni lettera maiuscola viene prima di ogni minuscola. Quindi Bilal è saltato in testa.
key=str.lower dice: mentre ordini, tratta ogni nome come se fosse minuscolo. I nomi stessi non cambiano — Bilal viene ancora stampato con la sua B maiuscola — solo il confronto usa la forma minuscola.
key può essere qualsiasi regola:
words = ["bag", "pen", "notebook", "ink"]
print(sorted(words, key=len))['bag', 'pen', 'ink', 'notebook']Ordinate per lunghezza. Nota che bag, pen e ink sono tutti e tre lunghi tre caratteri e sono rimasti nell'ordine in cui già si trovavano — Python non disturba i pari merito. Questa proprietà si chiama ordinamento stabile, ed è ciò che rende possibile ordinare per più criteri.
I tipi misti non si possono ordinare
values = [3, "1", 2]
print(sorted(values))TypeError: '<' not supported between instances of 'str' and 'int'Ordinare significa confrontare le cose a coppie, e il capitolo ottavo ha mostrato che un numero e un pezzo di testo non si possono confrontare con <. Il messaggio è parola per parola lo stesso. Questo capita regolarmente con le liste lette da un file CSV, dove ogni numero è in realtà testo.
Da una lista a testo — join
Stampare direttamente una lista ti dà parentesi e virgolette, che non vanno mostrate a una persona:
names = ["rafi", "ahmed", "bilal"]
print(", ".join(names))
print(" | ".join(names))rafi, ahmed, bilal
rafi | ahmed | bilalLa riga si legge al contrario la prima volta: il testo di unione viene primo, e la lista va tra le parentesi. Il modo per ricordarla — "unisci queste cose con questo".
C'è una condizione, ed è rigida: ogni valore deve essere testo.
marks = [72, 45, 90]
print(", ".join(marks))TypeError: sequence item 0: expected str instance, int foundPer unire una lista di numeri, trasforma prima ciascuno in testo:
marks = [72, 45, 90]
print(", ".join(str(m) for m in marks))72, 45, 90La parte str(m) for m in marks è nuova, e un capitolo successivo la insegna per intero. Per ora, leggila così: "per ogni m in marks, crea str(m)." Poi join unisce quelle stringhe. L'esempio completo qui sotto usa la stessa riga.
Un esempio completo
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 7Due decisioni di progettazione meritano attenzione.
È stato scelto sorted() invece di .sort() perché l'marks originale viene stampato di nuovo nella prima riga. Con .sort(), le righe "Marks" e "Ordered" avrebbero mostrato la stessa cosa e niente si sarebbe lamentato. È precisamente l'errore silenzioso con cui questo capitolo ha aperto.
I primi tre sono usciti da uno slice — ordered[:3]. Non serviva una funzione separata per "i primi tre": i primi tre di una lista in ordine decrescente sono i primi tre. Una volta che qualcosa è ordinato, un numero sorprendente di domande diventa uno slice.
Quando qualcosa va storto
La mia lista è diventata None dopo averla ordinata La riga diceva marks = marks.sort(). .sort() ordina la lista stessa e restituisce None — scrivi semplicemente marks.sort(). Per una nuova lista, ordered = sorted(marks).
L'ordinamento ha cambiato anche la lista originale Hai usato .sort(), che ordina al suo posto. Usa sorted() per lasciare intatta l'originale.
TypeError: '<' not supported between instances of 'str' and 'int' La lista mescola numeri e testo. Esegui print(marks) e guarda quali valori hanno le virgolette intorno; se proviene da un file probabilmente sono tutti testo, e servono int().
ValueError: 50 is not in list Ad index() o remove() è stato dato un valore che la lista non contiene. Controlla prima con in.
TypeError: sequence item 0: expected str instance, int found A join() è stata passata una lista di numeri. Metti ogni numero dentro str().
Dopo l'ordinamento dei nomi, tutti quelli con la maiuscola sono venuti prima È un comportamento corretto, non un bug. Per ordinare come una persona si aspetta, sorted(names, key=str.lower).
Passo 4 di 6 — Prevedi
Verifica cosa hai capito
sorted() è stato usato. Cosa stampano le due righe?
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]
Il risultato di .sort() viene salvato di nuovo in marks. Cosa viene stampato?
marks = [72, 45, 90]
marks = marks.sort()
print(marks)- AUn `AttributeError`
- B[72, 45, 90]
- C[45, 72, 90]
- DNone
Un tentativo di unire una lista di numeri con le virgole. Cosa succede?
marks = [72, 45, 90]
print(", ".join(marks))- AUn `TypeError` — `join` può unire solo testo
- B724590
- C72, 45, 90
- D[72, 45, 90]
Per rispondere serve un account
Accedi per verificare le tue risposte
Le domande sono qui sopra, e ragionarci a mente è la parte che conta. Accedi per vedere le risposte, le spiegazioni e i suggerimenti a tre livelli.
Tocca a te
Scrivi un file chiamato inventory.py che contiene una lista di almeno sette nomi di prodotti e una lista dei loro prezzi.
Dai prezzi, stampa:
- Il più alto, il più basso, il totale e la media (a due cifre decimali)
- Una nuova lista ordinata — e poi dimostra che l'originale non è cambiata
- I tre più costosi, usando uno slice
Dai nomi, stampa:
- L'ordine alfabetico, ignorando le maiuscole
- Ordinati per la lunghezza del nome
- Tutti i nomi su una riga, separati da virgola, usando
join
Poi esegui un esperimento: chiama .sort() sui prezzi, e stampa di nuovo le righe della parte 1. Quali numeri sono cambiati e quali no? Spiegati perché quelli che non sono cambiati non potevano cambiare — tieni stretta quella risposta e la trappola di questo capitolo non ti prenderà mai.
Passo 6 di 6
Sfida — il quiz del capitolo
Dieci domande dalla più facile alla più difficile. Le ultime sono difficili di proposito.
Accedi per fare il quiz