在日常使用 Python 時,我們經常需要創建一個串列,相信大家都很熟練了吧?
# 方法一:使用成對的方括號語法 list_a = [] # 方法二:使用內置的 list() list_b = list()
上面的兩種寫法,你經常使用哪一個呢?是否思考過它們的區別呢?
讓我們開門見山,直接拋出本文的問題吧:兩種創建串列的 [] 與 list() 寫法,哪一個更快呢,為什么它會更快呢?
注:為了簡化問題,我們以創建空串列為例進行分析
你們可能不知道,在Python 學習交流圈可以領取最新的Python學習資料
1、 [] 是 list() 的三倍快
對于第一個問題,使用timeit模塊的 timeit() 函式就能簡單地測算出來:
>>> import timeit >>> timeit.timeit('[]', number=10**7) >>> timeit.timeit('list()', number=10**7)

如上圖所示,在各自呼叫一千萬次的情況下,[] 創建方式只花費了 0.47 秒,而 list() 創建方式要花費 1.75 秒,所以,后者的耗時是前者的 3.7 倍!
這就回答了剛才的問題:創建空串列時,[] 要比 list() 快不少,
注:timeit() 函式的效率跟運行環境相關,每次執行結果會有微小差異,我在 Python3.8 版本實驗了幾次,總體上 [] 速度是 list() 的 3 倍多一點,
2、list() 比 [] 執行步驟多
那么,我們繼續來分析一下第二個問題:為什么 [] 會更快呢?
這一次我們可以使用dis模塊的 dis() 函式,看看兩者執行的位元組碼有何差別:
>>> from dis import dis >>> dis("[]") >>> dis("list()")

如上圖所示,[] 的位元組碼有兩條指令(BUILD_LIST 與 RETURN_VALUE),而 list() 的位元組碼有三條指令(LOAD_NAME、CALL_FUNCTION 與 RETURN_VALUE),
這些指令意味著什么呢?該如何理解呢?
首先,對于 [],它是 Python 中的一組字面量(literal),像數字之類的字面量一樣,表示確切的固定值,
也就是說,Python 在決議到它時,就知道它要表示一個串列,因此會直接呼叫解釋器中構建串列的方法(對應BUILD_LIST),來創建串列,所以是一步到位,
而對于 list(),“list”只是一個普通的名稱,并不是字面量,也就是說解釋器一開始并不認識它,
因此,解釋器的第一步是要找到這個名稱(對應LOAD_NAME),它會按照一定的順序,在各個作用域中逐一查找(區域作用域--全域作用域--內置作用域),直到找到為止,找不到則拋出NameError,
解釋器看到“list”之后是一對圓括號,因此第二步是把這個名稱當作可呼叫物件來呼叫,即把它當成一個函式進行呼叫(對應 CALL_FUNCTION),
因此,list() 在創建串列時,需要經過名稱查找與函式呼叫兩個步驟,才能真正開始創建串列(注:CALL_FUNCTION 在底層還會有一些函式呼叫程序,才能走到跟 BUILD_LIST 相通的邏輯,此處我們忽略不計),
至此,我們就可以回答前面的問題了:因為 list() 涉及的執行步驟更多,因此它比 [] 要慢一些,
3、list() 的速度提升
看完前兩個問題的解答程序,你也許覺得還不夠過癮,而且可能覺得就算知道了這個冷知識,也不會有多大的幫助,似乎那微弱的提升顯得微不足道,
但是,作者一直秉承著孜孜不倦的求知精神,是不可能放著這個問題不去回答的,
而且,由于有發散性思考的習慣,我還想到了另外一個挺有意思的問題:list() 的速度能否提升呢?
在剛剛發布的 Python 3.9.0 版本中,它給 list() 實作了更快的 vectorcall 協議,因此執行速度會有一定的提升,

感興趣的同學可以去 Python 官網下載 3.9 版本,
根據我多輪的測驗結果,在新版本中運行 list() 一千萬次,耗時大概在 1 秒左右,也就是 [] 運行耗時的 2 倍,相比于前面接近 4 倍的資料,當前版本總體上是提升了不少,
至此,我們已回答完一連串的疑問,如果你覺得有識訓,請點贊支持!歡迎大家關注后續更多精彩內容,
ps:我建立了一個Python學習圈子,點我就可以加入,在彼此的溝通可以我們可以得到很多學習經驗,積累知識,群內有很多有意思的腳本和庫,還有2020最新的python學習資料分享,大家可以一起討論問題,共同進步,
本文的文字及圖片來源于網路加上自己的想法,僅供學習、交流使用,不具有任何商業用途,著作權歸原作者所有,如有問題請及時聯系我們以作處理,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/185454.html
標籤:其他
下一篇:Java基礎語法:變數與常量
