2015-03-30 51 views
13

這很有趣; list()強制迭代器獲取實際列表的速度比[x for x in someList](理解)快得多。Python列表()vs列表理解構建速度

這是真的還是我的測試太簡單了? 下面是代碼:

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

對於10^6列表,Python 3.4給出5.5s vs 3.6s與'timeit'。 – 2015-03-30 22:06:25

+0

@ user5061:如果使用函數包裝並使用本地語言,則此處的計時會更好。在Python 3中,列表理解可以獲得自己的作用域(比如生成器表達式),而本地代碼更快。 – 2015-03-31 08:27:44

回答

13

列表內涵執行Python的字節碼的循環,就像一個普通的for循環。

list()調用完全使用C代碼進行迭代,速度更快。

的列表理解的字節碼如下:

>>> 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   

>>指針大致給你圈的邊界被執行,所以你有百萬STORE_NAMELOAD_NAMELIST_APPEND步驟的執行Python字節碼評估循環。

在另一方面list()只是直接通過使用對象迭代C API抓住從xrange()迭代的值,並且它可以使用xrange()對象的長度預先分配的列表對象,而不是動態地增長了。

+0

這只是一個實現細節?編譯器能夠在它看到它的時候自動轉換列表理解嗎? – 2015-03-30 21:51:36

+0

@KarolyHorvath:把它變成什麼? – 2015-03-30 21:53:51

+0

到快速版本:到一個'list(iterable)'形式(當然使用內建'list',以防本地定義)。從'[v for v in iterable]'形式。 – 2015-03-30 21:54:25