1 回答

TA貢獻(xiàn)1808條經(jīng)驗 獲得超4個贊
這是由于您構(gòu)建列表對象的方式:
x = [1] * 1000
這將創(chuàng)建一個只有一個對象的列表,引用了 1000 次;列表乘法不會創(chuàng)建值的副本。要理解為什么這很重要,我們需要看看 Python 列表是如何計算的。
list.count()可以像這樣看到循環(huán),用 C 編寫的實現(xiàn)的快速 Python 翻譯:
def count(self, value):
count = 0
for elem in self:
if elem == value:
count += 1
return count
這很簡單,對吧?但是,情況并非如此。實際代碼使用PyObject_RichCompareBool(),它首先測試對象身份。是真的:
if elem is value or elem == value:
當(dāng)所有列表元素都是同一個對象時,身份測試(簡單的指針相等測試)要快得多:
>>> import random
>>> v = random.randint(1000, 100000000)
>>> x = [v] * 1000
>>> all(value is v for value in x)
True
您可以使用任何隨機(jī)值重現(xiàn)它:
>>> from timeit import Timer
min(Timer('y=x.count(v)',setup='import random; v = random.randint(1000, 10000000); x=[v] * 1000').repeat(number=100000))
0.2716284029884264
>>> min(Timer('y=x.count(w)',setup='import random; v = random.randint(1000, 10000000); x=[v] * 1000; w = v + 1').repeat(number=100000))
1.0827720829984173
正如這些數(shù)字所示,在測試值相等之前進(jìn)行簡單的指針比較是很有意義的。這正是 Python 實現(xiàn)實習(xí)生某些經(jīng)常重用的值的原因,例如小整數(shù)(介于 -5 和 256 之間的整數(shù)),或者也是有效 Python 標(biāo)識符的字符串值。
如果你沒有在這里使用一個小整數(shù)作為x.count(); 的參數(shù),它就不會起作用。這是因為 1internedx.count(1)使用的對象也是列表的成員;x[0] is 1是真的。
添加回答
舉報