2012-06-19 26 views
8

tengo una lista de objetos:Crear una lista de atributos de los objetos en Python

[Object_1, Object_2, Object_3] 

Cada objeto tiene un atributo: Tiempo:

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

que desea crear una lista de los atributos de tiempo:

[20, 30, 40] 

¿Cuál es la forma más eficiente de obtener esta salida? No puede ser para iterar sobre la lista de objetos, ¿no ?:

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

'eficiente' está en el ojo del espectador ... –

+1

@Pyson: No, no, "eficiente" se mide en complejidad, tiempo de cálculo, líneas de código y/o uso de memoria. – Junuxx

+4

@Junuxx: la mayoría de las personas no prueba todas y cada una de las instancias de una comprensión frente a un bucle para ver cuál es menos ciclos de CPU. Si está usando Python, probablemente sea más fácil escribir y leer, no la velocidad absoluta. Lo que indicó allí, el tiempo de cálculo, las líneas de código y/o el uso de la memoria, pueden estar completamente en desacuerdo entre sí. El doble del código puede ser más rápido y usar menos memoria, pero toma más tiempo para leer y escribir como programador. ¿Qué es más * eficiente *? ¿Más rápido de ejecutar o más rápido para escribir en Python? Este es mi punto. –

Respuesta

23

lista por comprensión es lo que está buscando:

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

Tenga en cuenta que esto es tan eficiente como el código de OP. – Marcin

+0

@Marcin: en realidad, no está garantizado que las listas de comprensión sean igual, más o menos eficientes que la lista equivalente. Claro, puede averiguar la respuesta leyendo el código CPython (o los hilos de la lista de correo desde cuándo se propusieron las comprensiones de la lista), pero ¿puede suponer que se aplicaría a, digamos, PyPy? Entonces, una mejor cosa para decir es que no hay una buena razón para creer que esto será más eficiente. – abarnert

+4

¿Qué? Sí hay. Un bucle de comprensión de lista se realiza en el lado C, que es significativamente más rápido que un bucle de Python.Cualquier implementación será más rápida ya que una lista de comprensión es menos expresiva, por lo que se puede optimizar de manera más eficiente. –

2

¿Qué tal:

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

Tenga en cuenta que el mapa devuelve un generador, no una lista en 3.x, y que una lista de comprensión es mucho más legible (y probablemente más rápido) para algo como esto. –

+2

@Lattyware: +1. Y si realmente desea un generador, puede usar una expresión del generador tan fácilmente como una lista de comprensión. – abarnert

2

El más rápido (y el más fácil de entender) es con una lista de comprensión.

Ver el calendario:

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' 

Prints:

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 

Así lista por comprensión es a la vez más rápido y más rápido para escribir a ejecutar.

Cuestiones relacionadas