È un po 'intelligente.
Innanzitutto, come notato in un commento, in Python 3 zip()restituisce un iteratore, quindi è necessario racchiudere il tutto list()per ottenere un elenco effettivo, quindi a partire dal 2020 è in realtà:
list(zip(*original[::-1]))
Ecco la ripartizione:
[::-1]- crea una copia superficiale dell'elenco originale in ordine inverso. Potrebbe anche usare reversed()che produrrebbe un iteratore inverso sulla lista piuttosto che copiarla effettivamente (più efficiente in termini di memoria).
*- rende ogni sottolista nell'elenco originale un argomento separato per zip()(cioè, decomprime l'elenco)
zip()- prende un elemento da ogni argomento e crea un elenco (beh, una tupla) da quelli, e si ripete finché tutte le sottoliste non sono esaurite. È qui che avviene la trasposizione.
list()converte l'output di zip()in un elenco.
Quindi supponendo che tu abbia questo:
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
Per prima cosa ottieni questo (copia superficiale e invertita):
[ [7, 8, 9],
[4, 5, 6],
[1, 2, 3] ]
Successivamente ciascuna delle sottoliste viene passata come argomento a zip:
zip([7, 8, 9], [4, 5, 6], [1, 2, 3])
zip() consuma ripetutamente un elemento dall'inizio di ciascuno dei suoi argomenti e ne crea una tupla, fino a quando non ci sono più elementi, risultando (dopo che è stato convertito in un elenco):
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
E Bob è tuo zio.
Per rispondere alla domanda di @ IkeMiguel in un commento sulla rotazione nell'altra direzione, è abbastanza semplice: devi solo invertire sia le sequenze che entrano in gioco zipche il risultato. Il primo può essere ottenuto rimuovendo il [::-1]e il secondo può essere ottenuto lanciando un reversed()intorno al tutto. Dal momento che reversed()restituisce un iteratore sulla lista, avremo bisogno di mettere list()in giro che per convertirlo. Con un paio di list()chiamate extra per convertire gli iteratori in un elenco effettivo. Così:
rotated = list(reversed(list(zip(*original))))
Possiamo semplificarlo un po 'usando la sezione "smiley marziano" piuttosto che reversed()... quindi non abbiamo bisogno dell'esterno list():
rotated = list(zip(*original))[::-1]
Ovviamente, potresti anche ruotare l'elenco in senso orario tre volte. :-)