2012-06-19 14 views
8

Ho una lista di oggetti:Crea lista di oggetti attributi in python

[Object_1, Object_2, Object_3] 

Ogni oggetto ha un attributo: tempo:

Object_1.time = 20 
Object_2.time = 30 
Object_3.time = 40 

voglio creare una lista di attributi di tempo:

[20, 30, 40] 

Qual è il modo più efficiente per ottenere questo risultato? Non può essere per scorrere la lista degli oggetti, giusto ?:

items = [] 
for item in objects: 
    items.append(item.time) 
+0

"efficiente" è negli occhi di chi guarda ... –

+1

@Pyson: No, non lo è, "efficiente" viene misurato in complessità, tempo di calcolo, linee di codice e/o utilizzo della memoria. – Junuxx

+4

@Junuxx: la maggior parte delle persone non verifica ogni singola istanza di comprensione rispetto a un ciclo per vedere quali sono i cicli di CPU meno numerosi. Se si utilizza Python, è probabilmente sulla facilità di scrivere e leggere, non sulla velocità assoluta. Quello che hai affermato lì, tempo di calcolo, linee di codice e/o utilizzo della memoria, potrebbe essere completamente in disaccordo tra loro. Raddoppiare il codice potrebbe essere più veloce e utilizzare meno memoria, ma richiede più tempo per leggere e scrivere come programmatore. Quale è più * efficiente *? Più veloce da eseguire o più veloce da scrivere in Python? Questo è il mio punto. –

risposta

23

di lista è quello che stai dopo:

list_of_objects = [Object_1, Object_2, Object_3] 
[x.time for x in list_of_objects] 
+0

Si noti che questo è efficiente come il codice OP. – Marcin

+0

@Marcin: In realtà, non è garantito da nessuna parte che la comprensione delle liste sia ugualmente, più o meno efficiente della lista equivalente. Certo, puoi capire la risposta leggendo il codice CPython (o i thread della mailing list da quando sono state proposte le comprensioni delle liste), ma puoi presumere che si applicherebbe, per esempio, a PyPy? Quindi, una cosa migliore da dire è che non ci sono buone ragioni per credere che questo sarà più efficiente. – abarnert

+4

Cosa? Si C'è. Un ciclo di comprensione delle liste viene eseguito sul lato C, che è significativamente più veloce di un loop Python.Qualsiasi implementazione sarà più veloce in quanto la comprensione di una lista è una cosa meno espressiva, e quindi può essere ottimizzata in modo più efficiente. –

2

ne dite:

items=[item.time for item in objects] 
2
from operator import attrgetter 
items = map(attrgetter('time'), objects) 
+1

Si noti che la mappa restituisce un generatore, non una lista in 3.x, e che una comprensione delle liste è molto più leggibile (e probabilmente più veloce) per qualcosa di simile. –

+2

@Lattyware: +1. E se in realtà _ vuoi un generatore, puoi usare un'espressione di generatore con la stessa facilità di una comprensione di lista. – abarnert

2

Il più veloce (e più facile da capire) è con una lista di comprensione.

Vedere i tempi:

import timeit 
import random 
c=10000 

class SomeObj: 
    def __init__(self, i): 
     self.attr=i 

def loopCR(): 
    l=[] 
    for i in range(c): 
     l.append(SomeObj(random.random())) 

    return l 

def compCR(): 
    return [SomeObj(random.random()) for i in range(c)] 

def loopAc(): 
    lAttr=[] 
    for e in l: 
     lAttr.append(e.attr) 

    return lAttr 

def compAc(): 
    return [e.attr for e in l]    

t1=timeit.Timer(loopCR).timeit(10) 
t2=timeit.Timer(compCR).timeit(10) 
print "loop create:", t1,"secs" 
print "comprehension create:", t2,"secs" 
print 'Faster of those is', 100.0*abs(t1-t2)/max(t1,t2), '% faster' 
print 

l=compCR() 

t1=timeit.Timer(loopAc).timeit(10) 
t2=timeit.Timer(compAc).timeit(10) 
print "loop access:", t1,"secs" 
print "comprehension access:", t2,"secs" 
print 'Faster of those is', 100.0*abs(t1-t2)/max(t1,t2), '% faster' 

Stampe:

loop create: 0.103852987289 secs 
comprehension create: 0.0848100185394 secs 
Faster of those is 18.3364670069 % faster 

loop access: 0.0206878185272 secs 
comprehension access: 0.00913000106812 secs 
Faster of those is 55.8677438315 % faster 

Quindi di lista è sia più veloce di scrivere e più veloce da eseguire.