2012-07-11 13 views
11

Ho notato qualcosa che non mi aspettavo quando ho scritto una sceneggiatura stamattina. Ho provato ad usare una list comprehension e ad ordinare tutto in una sola affermazione ottenendo un risultato sorprendente. Il codice seguente riassume il mio caso uso generale, ma è semplificata per questa domanda:Ordinamento di una comprensione di lista in una istruzione

Transaction = namedtuple('Transaction', ['code', 'type']) 

my_list = [Transaction('code1', 'AAAAA'), Transaction('code2', 'BBBBB'), Transaction('code3', 'AAAAA')] 

types = ['AAAAA', 'CCCCC'] 

result = [trans for trans in my_list if trans.type in types].sort(key = lambda x: x.code) 

print result 

uscita:

None 

Se creo l'elenco utilizzando la comprensione, poi ordinare dopo il fatto, tutto è bene. Sono curioso perché questo succede?

+2

i metodi 'sort' ordina l'elenco * in-place * e quindi restituisce' None'. – sloth

risposta

21

Il metodo list.sort() è l'ordinamento della lista a posto, e come tutti i metodi mutanti che restituisce None. Utilizzare la funzione incorporata sorted() per restituire un nuovo elenco ordinato.

result = sorted((trans for trans in my_list if trans.type in types), 
       key=lambda x: x.code) 

Invece di lambda x: x.code, si potrebbe anche utilizzare il leggermente più veloce operator.attrgetter("code").

0

si desidera la funzione incorporata sorted. Il metodo sort ordina un elenco e restituisce None.

result = sorted([trans for trans in my_list if trans.type in types],key = lambda x: x.code) 

questo potrebbe essere fatto un po 'meglio da:

import operator 
result = sorted((trans for trans in my_list if trans.type in types), key=operator.attrgetter("code")) 
+0

Si noti che passare una comprensione di lista a 'sorted()' comporta una copia dell'elenco che si sta facendo. Questo non è necessariamente più lento, ma potrebbe comportare un maggiore consumo di memoria. –

+0

È necessario racchiudere l'espressione del generatore tra parentesi. –

+0

@SvenMarnach - Non hai bisogno di parentesi, vero? 'ordinata (x per x in xrange (10))' funziona perfettamente per me – mgilson

2

Chiamare .sort in un elenco restituisce None. È perfettamente logico che questo risultato venga quindi assegnato a result.

In altre parole, si crea un elenco anonimo con una lista di comprensione, quindi chiamare .sort, e la lista è perduto mentre il risultato della chiamata .sort viene memorizzato nella variabile result.

Come altri hanno già detto, è necessario utilizzare la funzione integrata sorted() per restituire un elenco. (sorted() restituisce una copia ordinata dell'elenco.)

Problemi correlati