亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

count() 的奇怪執行次數

count() 的奇怪執行次數

開滿天機 2022-07-05 17:51:45
編碼:from timeit import Timerprint(min(Timer('y=x.count(1)',setup='x=[1] * 1000').repeat(number=1000000))) print(min(Timer('y=x.count(0)',setup='x=[1] * 1000').repeat(number=1000000)))我機器上的結果:0.703322878922335810.16116041096393誰能解釋為什么第一種情況比第二種情況快得多?我預計這兩次都會相似。
查看完整描述

1 回答

?
炎炎設計

TA貢獻1808條經驗 獲得超4個贊

這是由于您構建列表對象的方式:


x = [1] * 1000    

這將創建一個只有一個對象的列表,引用了 1000 次;列表乘法不會創建值的副本。要理解為什么這很重要,我們需要看看 Python 列表是如何計算的。


list.count()可以像這樣看到循環,用 C 編寫的實現的快速 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:

當所有列表元素都是同一個對象時,身份測試(簡單的指針相等測試)要快得多:


>>> import random

>>> v = random.randint(1000, 100000000)

>>> x = [v] * 1000

>>> all(value is v for value in x)

True

您可以使用任何隨機值重現它:


>>> 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

正如這些數字所示,在測試值相等之前進行簡單的指針比較是很有意義的。這正是 Python 實現實習生某些經常重用的值的原因,例如小整數(介于 -5 和 256 之間的整數),或者也是有效 Python 標識符的字符串值。


如果你沒有在這里使用一個小整數作為x.count(); 的參數,它就不會起作用。這是因為 1internedx.count(1)使用的對象也是列表的成員;x[0] is 1是真的。


查看完整回答
反對 回復 2022-07-05
  • 1 回答
  • 0 關注
  • 127 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號