2015-03-30 21 views
13

Dies ist interessant; list(), um einen Iterator zu zwingen, die tatsächliche Liste zu bekommen, ist so viel schneller als [x for x in someList] (Verständnis).Python-Liste() vs Liste Verständnis Gebäude Geschwindigkeit

Ist das echt oder ist mein Test einfach zu einfach? Unten ist der Code:

import time  

timer = time.clock() 
for i in xrange(90): 

    #localList = [x for x in xrange(1000000)] #Very slow, took me 6.8s 
    localList = list(xrange(1000000))   #Very fast, took me 0.9s 

    print localList[999999] #make sure list is really evaluated. 

print "Total time: ", time.clock() - timer 
+0

Python 3.4 gibt 5.5s vs 3.6s mit 'timeit', für eine 10^6 Liste. –

+0

@ user5061: die Zeiten hier wären viel besser, wenn sie in eine Funktion eingepackt und Einheimische benutzt werden. In Python 3 erhält ein Listenverständnis seinen eigenen Geltungsbereich (wie ein Generatorausdruck) und Locals sind schneller. –

Antwort

13

Die Liste Verständnis der Schleife in Python-Bytecode ausführt, wie eine normale for Schleife.

Der Aufruf list() iteriert vollständig im C-Code, der viel schneller ist.

Der Bytecode für die Liste Verständnis sieht wie folgt aus:

>>> import dis 
>>> dis.dis(compile("[x for x in xrange(1000000)]", '<stdin>', 'exec')) 
    1   0 BUILD_LIST    0 
       3 LOAD_NAME    0 (xrange) 
       6 LOAD_CONST    0 (1000000) 
       9 CALL_FUNCTION   1 
      12 GET_ITER    
     >> 13 FOR_ITER    12 (to 28) 
      16 STORE_NAME    1 (x) 
      19 LOAD_NAME    1 (x) 
      22 LIST_APPEND    2 
      25 JUMP_ABSOLUTE   13 
     >> 28 POP_TOP    
      29 LOAD_CONST    1 (None) 
      32 RETURN_VALUE   

Die >> Zeiger Sie grob geben die Grenzen der Schleife ausgeführt wird, so haben Sie eine Million STORE_NAME, LOAD_NAME und LIST_APPEND Schritte in der zur Ausführung Python-Bytecode-Auswertungsschleife.

list() auf der anderen Seite greift nur die Werte aus dem xrange() iterable direkt durch den C-API für das Objekt Iteration verwendet wird, und es kann die Länge des xrange()-Objekts verwenden, um die Liste Objekt vorbelegt, anstatt sich dynamisch wachsen.

+0

Ist das nur ein Implementierungsdetail? Könnte der Compiler automatisch das Verständnis der Liste transformieren, wann immer er es in dieser Form sieht? –

+0

@KarolyHorvath: Verwandeln Sie es in was genau? –

+0

zu der schnellen Version: zu einer 'Liste (iterable)' Form (natürlich mit der eingebauten 'liste', falls es lokal definiert wurde). aus der '[v für v in iterable]' Form. –