2013-06-03 108 views
3

爲什麼列表理解有更好的性能比for循環,在Python中?Python List Comprehension vs

列表理解:

new_items = [a for a in items if a > 10] 

for循環:

new_items = [] 
for a in items: 
    if a > 10: new_items.append(a) 

是否還有其他的例子(不循環),其中一個Python的結構具有比另一個Python結構性能差?

+2

*是否有其他示例(非循環),當一個Python結構比其他Python結構的性能差?* - 無限多。 –

+0

@Lattyware,例如? –

+5

如果性能是唯一的原因,你不應該太擔心lc vs loop。擔心你的整體算法是健全的,並擔心你可以理解你編寫的代碼。 – dawg

回答

8

從本質上講,列表理解和循環做的事情非常相似,列表理解消除了一些開銷並使其看起來很漂亮。 要理解爲什麼這是更快,你應該看看在Efficiency of list comprehensions和引用有關問題的相關部分:

列表理解這裏更好地發揮,因爲你不需要加載 追加屬性關閉名單(循環程序,字節碼28)和 稱之爲函數(循環程序,字節碼38)。相反,在 的理解中,爲快速附加到結果列表(理解程序,字節碼33)上的 生成專用的LIST_APPEND字節碼。

在loop_faster程序,你避免追加 屬性查找的開銷提升它的循環,並把結果 在fastlocal(字節碼9-12),所以它更快速地循環;然而, 理解使用專門的LIST_APPEND字節碼而不是 招致函數調用的開銷,所以它仍然勝過。

該鏈接還詳細介紹了與lc相關的一些可能的缺陷,我建議您通過一次。

+0

如果你想要時間你的代碼,你可以使用''%timeit' 'ipython中的神奇功能 – goofd

+0

LC不需要擔心語句之類的事情,因爲LC中只允許表達式。 –

+0

這不太好。這是非常長的聲明,所以我必須將其分成多行。一旦出現這種情況,理解對我來說就沒什麼意義了:'[[如果item_idx == row_idx其他0爲範圍(0,3)中的item_idx]]爲範圍(0,3)]中的row_idx] https://python-3-patterns-idioms-test.readthedocs.org/en/latest/Comprehensions.html。 – Schultz9999

1

the python wiki

for語句是最常用的。它遍歷 一個序列的元素,將每個元素分配給循環變量。如果 循環的主體很簡單,那麼for循環的解釋器開銷本身可能是大量的開銷。這是地圖功能 方便的地方。你可以把map看作一個移動到C代碼的地方。

如此簡單的循環有列表解析帶來的開銷。

3

假設我們在這裏談論CPython中,您可以使用dis模塊比較生成的字節碼:

>> def one(): 
     return [a for a in items if a > 10] 

>> def two(): 
     res = [] 
     for a in items: 
      if a > 10: 
       res.append(a) 

>> dis.dis(one) 

    2   0 BUILD_LIST    0 
       3 LOAD_GLOBAL    0 (items) 
       6 GET_ITER 
     >> 7 FOR_ITER    24 (to 34) 
      10 STORE_FAST    0 (a) 
      13 LOAD_FAST    0 (a) 
      16 LOAD_CONST    1 (10) 
      19 COMPARE_OP    4 (>) 
      22 POP_JUMP_IF_FALSE  7 
      25 LOAD_FAST    0 (a) 
      28 LIST_APPEND    2 
      31 JUMP_ABSOLUTE   7 
     >> 34 RETURN_VALUE 

>> dis.dis(two) 
    2   0 BUILD_LIST    0 
       3 STORE_FAST    0 (res) 

    3   6 SETUP_LOOP    42 (to 51) 
       9 LOAD_GLOBAL    0 (items) 
      12 GET_ITER 
     >> 13 FOR_ITER    34 (to 50) 
      16 STORE_FAST    1 (a) 

    4   19 LOAD_FAST    1 (a) 
      22 LOAD_CONST    1 (10) 
      25 COMPARE_OP    4 (>) 
      28 POP_JUMP_IF_FALSE  13 

    5   31 LOAD_FAST    0 (res) 
      34 LOAD_ATTR    1 (append) 
      37 LOAD_FAST    1 (a) 
      40 CALL_FUNCTION   1 
      43 POP_TOP 
      44 JUMP_ABSOLUTE   13 
      47 JUMP_ABSOLUTE   13 
     >> 50 POP_BLOCK 
     >> 51 LOAD_CONST    0 (None) 
      54 RETURN_VALUE 

因此,對於一兩件事,列表解析需要專用LIST_APPEND操作碼這是不的優勢被for循環使用。

相關問題