2009-02-01 5 views
7

Cosa significa l'ultima riga nel seguente codice?Problema nella comprensione delle liste di Python

import pickle, urllib                                      

    handle = urllib.urlopen("http://www.pythonchallenge.com/pc/def/banner.p") 
    data = pickle.load(handle) 
    handle.close() 

    for elt in data: 
     print "".join([e[1] * e[0] for e in elt]) 

Il mio tentativo di problema:

  • "" .join ... usi uniscono -Metodo di testo vuota
  • e [1] * e [0] moltiplica due valori successivi la sequenza, e
  • non sono sicuro di ciò che è e
  • non sono sicuro, che cosa significa, quando si ha qualcosa prima per -loop, come: e[1] * e[0] for e in elt
+0

Mi è piaciuta molto la sfida Python quando l'ho scattata un paio di anni fa. –

risposta

19

Forse meglio spiegato con un esempio:

print "".join([e[1] * e[0] for e in elt]) 

è l'abbreviazione di

x = [] 
for e in elt: 
    x.append(e[1] * e[0]) 
print "".join(x) 

Elenco comprehensions sono zucchero semplicemente sintattica per for cicli, che rendono l'espressione di una sequenza di istruzioni .

elt può essere un oggetto arbitrario, poiché lo si carica dai sottaceti e e allo stesso modo. L'utilizzo suggerisce che si tratta di un tipo sequence, ma potrebbe essere semplicemente qualsiasi cosa che implementa il protocollo di sequenza.

+0

Penso che tu intenda "x.append (e [1] * e [0])" .. –

+0

@Marek: John ha ragione. –

+0

@John: certo, è corretto. –

4

[e[1] * e[0] for e in elt] è una comprensione di lista, che valuta un elenco stesso eseguendo il ciclo attraverso un altro elenco, in questo caso elt. Ogni elemento nel nuovo elenco è e[1]*e[0], dove e è l'elemento corrispondente in elt.

+0

e potrebbe essere una tupla o dict – SilentGhost

+0

e potrebbe essere qualsiasi cosa che implementa __getitem__. –

+0

È vero, ho fatto una brutta ipotesi. –

1

join() è un metodo di stringa, che funziona su un separatore nella nuova stringa

>>> ':'.join(['ab', 'cd']) 
>>> 'ab:cd' 

e di lista non è necessario lì, generatore basterebbe

7

In primo luogo, è necessario mettere http: // prima dell'URL, cioè: maniglia = urllib.urlopen ("http://www.pythonchallenge.com/pc/def/banner.p")

un'espressione [e per posta in aList] è un list comprehension che genera un elenco di valori.

Con le stringhe Python, l'operatore * viene utilizzato per ripetere una stringa. Provate a digitare nei comandi uno per uno in un interprete poi guardare i dati:

>>> data[0] 
[(' ', 95)] 

Questo ci mostra ogni riga di dati è una tupla contenente due elementi.

Quindi l'espressione e 1 * e [0] è effettivamente la stringa in e [0] ripetuta e 1 volte.

Quindi il programma disegna un banner.

+0

Ma cambia gli elementi: e [0] = 95 ed e [1] = ''. –

+0

grazie per la correzione - Sono così abituato a fare la cosa "sensibile" di moltiplicare una stringa per un intero che ho letto come tale, soprattutto perché è così che i dati vengono memorizzati! –

1

Andy's è un'ottima risposta!

Se volete vedere ogni fase del ciclo (con la linea-break) provare questo fuori:

for elt in data: 
    for e in elt: 
     print "e[0] == %s, e[1] == %d, which gives us: '%s'" % (e[0], e[1], ''.join(e[1] * e[0])) 
+0

Fornisce una lunga lista di: e [0] ==% s, e [1] ==% d –

+0

@Masi: Grazie per averlo notato. Forse il carattere di interruzione di riga ("\") stava causando problemi. L'ho rimosso dalla risposta. – bernie

2

La domanda stessa è già stata completamente risolta, ma vorrei aggiungere che una list comprehension supporta anche il filtraggio. Vostra linea originale

print "".join([e[1] * e[0] for e in elt]) 

potrebbe, ad esempio, diventare

print "".join([e[1] * e[0] for e in elt if len(e) == 2]) 

operare soltanto sugli articoli in elt che hanno due elementi.

+0

Degno commento! – ChuckCottrill