2015-04-29 54 views
2

我試圖找到切片分配和列表的常規分配之間的性能差異。下面是代碼:256之後的列表理解分配/比較失敗

import time 

N = 1000 
a = list(range(N)) 
b = list(range(N)) 

time1 = time.time() 
for i in range(N): 
    a = [x for x in a if x is not i] 
time2 = time.time() 
for i in range(N): 
    b[:] = [x for x in b if x is not i] 
time3 = time.time() 

print a 
print b  
print time2 - time1 
print time3 - time2 

我的期望是,每個列表ab,這一次刪除一個元素,使print aprint b都打印空列表。相反,他們似乎總是打印起始列表,但缺少第一個256元素。

它們都打印:

[257, 258, 259 ... N-1] 

這是怎麼回事?

我正在使用Python 2.7.6。

+2

因爲小整數在CPython中被緩存,所以使用'!='而不是'is'運算符。 –

回答

6

問題是,您正在使用is而不是==

前者檢查對象身份,不等於。沒有理由相信評估,例如,300+1兩次會給你同樣的int對象,只是他們會給你int對象的值爲301

這發生在「工作」的人數達到256,因爲您的特定Python實現*恰好實習生整數高達256啓動時,它的數量12創建一個單獨的對象,一個單一對象,等等。任何時候表達式的計算結果都是1,它會給你那個對象,而不是一個新對象。 **

不用說,你不應該依賴那個優化。


* IIRC,CPython中的每個版本從1.x的日子到3.5默認這種行爲從-5到256的所有整數,但你可以改變這些限制,或關閉該功能,在構建時間,而不同的實現可能會做一些不同的事情。

**如果你想知道這是如何工作的CPython的,在C API級別,PyLong_FromLong從-5到256單值的數組中查找號碼做到這一點。您可以看到3.4版本的代碼,例如,here;宏CHECK_SMALL_INT和它調用的實際函數get_small_int以及函數使用的靜態數組都是在同一個文件中,靠近頂部。