![](/img/trans.png)
[英]why is function with a list comprehension statement *faster* than the list comprehension statement?
[英]Why list comprehension can be faster than map() in Python?
測試一 :扔掉結果。
這是我們的虛擬功能:
def examplefunc(x):
pass
以下是我們的挑戰者:
def listcomp_throwaway():
[examplefunc(i) for i in range(100)]
def forloop_throwaway():
for i in range(100):
examplefunc(i)
根據OP的問題,我不會對其原始速度進行分析,只是為什么 。 讓我們來看看機器代碼的差異。
--- List comprehension
+++ For loop
@@ -1,15 +1,16 @@
- 55 0 BUILD_LIST 0
+ 59 0 SETUP_LOOP 30 (to 33)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (100)
9 CALL_FUNCTION 1
12 GET_ITER
- >> 13 FOR_ITER 18 (to 34)
+ >> 13 FOR_ITER 16 (to 32)
16 STORE_FAST 0 (i)
- 19 LOAD_GLOBAL 1 (examplefunc)
+
+ 60 19 LOAD_GLOBAL 1 (examplefunc)
22 LOAD_FAST 0 (i)
25 CALL_FUNCTION 1
- 28 LIST_APPEND 2
- 31 JUMP_ABSOLUTE 13
- >> 34 POP_TOP
- 35 LOAD_CONST 0 (None)
- 38 RETURN_VALUE
+ 28 POP_TOP
+ 29 JUMP_ABSOLUTE 13
+ >> 32 POP_BLOCK
+ >> 33 LOAD_CONST 0 (None)
+ 36 RETURN_VALUE
比賽開始了。 Listcomp的第一步是建立一個空列表,而for循環是建立一個循環。 然后它們都繼續加載全局范圍(),常量100,並調用生成器的范圍函數。 然后他們都獲得當前的迭代器並獲得下一個項目,並將其存儲到變量i中。 然后他們加載examplefunc和i並調用examplefunc。 Listcomp將它附加到列表並再次開始循環。 For循環在三個指令中執行相同而不是兩個。 然后他們都加載None並返回它。
那么誰在這個分析中似乎更好? 在這里,列表理解會執行一些冗余操作,例如構建列表並附加到它,如果您不關心結果。 For循環也非常有效。
如果你計時,使用for循環比列表理解快三分之一。 (在這個測試中,examplefunc將其參數除以5並將其拋棄而不是什么都不做。)
測試二 :保持結果正常。
這個測試沒有虛函數。 所以這是我們的挑戰者:
def listcomp_normal():
l = [i*5 for i in range(100)]
def forloop_normal():
l = []
for i in range(100):
l.append(i*5)
差異對我們今天沒用。 它只是兩個塊中的兩個機器碼。
列出comp的機器代碼:
55 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (100)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 16 (to 32)
16 STORE_FAST 0 (i)
19 LOAD_FAST 0 (i)
22 LOAD_CONST 2 (5)
25 BINARY_MULTIPLY
26 LIST_APPEND 2
29 JUMP_ABSOLUTE 13
>> 32 STORE_FAST 1 (l)
35 LOAD_CONST 0 (None)
38 RETURN_VALUE
對於循環的機器代碼:
59 0 BUILD_LIST 0
3 STORE_FAST 0 (l)
60 6 SETUP_LOOP 37 (to 46)
9 LOAD_GLOBAL 0 (range)
12 LOAD_CONST 1 (100)
15 CALL_FUNCTION 1
18 GET_ITER
>> 19 FOR_ITER 23 (to 45)
22 STORE_FAST 1 (i)
61 25 LOAD_FAST 0 (l)
28 LOAD_ATTR 1 (append)
31 LOAD_FAST 1 (i)
34 LOAD_CONST 2 (5)
37 BINARY_MULTIPLY
38 CALL_FUNCTION 1
41 POP_TOP
42 JUMP_ABSOLUTE 19
>> 45 POP_BLOCK
>> 46 LOAD_CONST 0 (None)
49 RETURN_VALUE
正如您可能已經知道的那樣,列表理解的指令少於循環。
列表理解的清單:
range
。 100
。 range
。 i
。 i
。 l
指向匿名空列表。 對於循環的核對清單:
l
指向匿名空列表。 range
。 100
。 range
。 i
。 l
。 append
。 i
。 append
。 (不包括以下步驟:加載None
,返回。)
列表理解不必執行以下操作:
i
兩次 總之,如果要使用這些值,listcomp要快得多,但如果不這樣做,那么速度非常慢。
真正的速度
測試一:for循環速度快三分之一*
測試二:列表理解速度提高了大約三分之二*
*關於 - >小數點后第二位
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.