爲什麼列表理解有更好的性能比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結構性能差?
爲什麼列表理解有更好的性能比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結構性能差?
從本質上講,列表理解和循環做的事情非常相似,列表理解消除了一些開銷並使其看起來很漂亮。 要理解爲什麼這是更快,你應該看看在Efficiency of list comprehensions和引用有關問題的相關部分:
列表理解這裏更好地發揮,因爲你不需要加載 追加屬性關閉名單(循環程序,字節碼28)和 稱之爲函數(循環程序,字節碼38)。相反,在 的理解中,爲快速附加到結果列表(理解程序,字節碼33)上的 生成專用的LIST_APPEND字節碼。
在loop_faster程序,你避免追加 屬性查找的開銷提升它的循環,並把結果 在fastlocal(字節碼9-12),所以它更快速地循環;然而, 理解使用專門的LIST_APPEND字節碼而不是 招致函數調用的開銷,所以它仍然勝過。
該鏈接還詳細介紹了與lc相關的一些可能的缺陷,我建議您通過一次。
如果你想要時間你的代碼,你可以使用''%timeit' 'ipython中的神奇功能 – goofd
LC不需要擔心語句之類的事情,因爲LC中只允許表達式。 –
這不太好。這是非常長的聲明,所以我必須將其分成多行。一旦出現這種情況,理解對我來說就沒什麼意義了:'[[如果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
for語句是最常用的。它遍歷 一個序列的元素,將每個元素分配給循環變量。如果 循環的主體很簡單,那麼for循環的解釋器開銷本身可能是大量的開銷。這是地圖功能 方便的地方。你可以把map看作一個移動到C代碼的地方。
如此簡單的循環有列表解析帶來的開銷。
假設我們在這裏談論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循環使用。
*是否有其他示例(非循環),當一個Python結構比其他Python結構的性能差?* - 無限多。 –
@Lattyware,例如? –
如果性能是唯一的原因,你不應該太擔心lc vs loop。擔心你的整體算法是健全的,並擔心你可以理解你編寫的代碼。 – dawg