成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入Python列表的內(nèi)部實現(xiàn)

開發(fā) 后端
本文將介紹列表在 CPython中的實現(xiàn),因為畢竟Cpython 又是 Python 最為常用的實現(xiàn)。

本文將介紹列表在 CPython中的實現(xiàn),因為畢竟Cpython 又是 Python 最為常用的實現(xiàn)。

Python 中的列表非常強大,看看它的內(nèi)部實現(xiàn)機制是怎么樣的,一定非常有趣。

下面是一段 Python 腳本,在列表中添加幾個整數(shù),然后打印列表。

  1. >>> l = [] 
  2.  
  3. >>> l.append(1) 
  4.  
  5. >>> l.append(2) 
  6.  
  7. >>> l.append(3) 
  8.  
  9. >>> l 
  10.  
  11. [1, 2, 3] 
  12.  
  13. >>> for e in l: 
  14.  
  15. ...   print e 
  16.  
  17. ... 
  18.  
  19.  
  20.  
  21.  

可以發(fā)現(xiàn),列表是一個迭代器。

列表對象的 C 語言結構體

Cpython 中的列表實現(xiàn)類似于下面的 C 結構體。ob_item 是指向列表對象的指針數(shù)組。allocated 是申請內(nèi)存的槽的個數(shù)。

  1. typedef struct { 
  2.  
  3.     PyObject_VAR_HEAD 
  4.  
  5.     PyObject **ob_item; 
  6.  
  7.     Py_ssize_t allocated; 
  8.  
  9. } PyListObject;  

列表初始化

看看初始化一個空列表的時候發(fā)生了什么,例如:l = []。

  1. arguments: size of the list = 0 
  2.  
  3. returns: list object = [] 
  4.  
  5. PyListNew: 
  6.  
  7.     nbytes = size * size of global Python object = 0 
  8.  
  9.     allocate new list object 
  10.  
  11.     allocate list of pointers (ob_item) of size nbytes = 0 
  12.  
  13.     clear ob_item 
  14.  
  15.     set list's allocated var to 0 = 0 slots 
  16.  
  17.     return list object  

要分清列表大小和分配的槽大小,這很重要。列表的大小和 len(l) 的大小相同。分配槽的大小是指已經(jīng)在內(nèi)存中分配了的槽空間數(shù)。通常分配的槽的大小要大于列表大小,這是為了避免每次列表添加元素的時候都調(diào)用分配內(nèi)存的函數(shù)。下面會具體介紹。

Append 操作

向列表添加一個整數(shù):l.append(1) 時發(fā)生了什么?調(diào)用了底層的 C 函數(shù) app1()。

  1. arguments: list object, new element 
  2.  
  3. returns: 0 if OK, -1 if not 
  4.  
  5. app1: 
  6.  
  7.     n = size of list 
  8.  
  9.     call list_resize() to resize the list to size n+1 = 0 + 1 = 1 
  10.  
  11.     list[n] = list[0] = new element 
  12.  
  13.     return 0  

下面是 list_resize() 函數(shù)。它會多申請一些內(nèi)存,避免頻繁調(diào)用 list_resize() 函數(shù)。列表的增長模式為:0,4,8,16,25,35,46,58,72,88……

  1. arguments: list object, new size 
  2.  
  3. returns: 0 if OK, -1 if not 
  4.  
  5. list_resize: 
  6.  
  7.     new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6) = 3 
  8.  
  9.     new_allocated += newsize = 3 + 1 = 4 
  10.  
  11.     resize ob_item (list of pointers) to size new_allocated 
  12.  
  13.     return 0  

現(xiàn)在分配了 4 個用來裝列表元素的槽空間,并且***個空間中為整數(shù) 1。如下圖顯示 l[0] 指向我們新添加的整數(shù)對象。虛線的方框表示已經(jīng)分配但沒有使用的槽空間。

列表追加元素操作的平均復雜度為 O(1)。

 

繼續(xù)添加新的元素:l.append(2)。調(diào)用 list_resize 函數(shù),參數(shù)為 n+1 = 2, 但是因為已經(jīng)申請了 4 個槽空間,所以不需要再申請內(nèi)存空間。再添加兩個整數(shù)的情況也是一樣的:l.append(3),l.append(4)。下圖顯示了我們現(xiàn)在的情況。  

 

Insert 操作

在列表偏移量 1 的位置插入新元素,整數(shù) 5:l.insert(1,5),內(nèi)部調(diào)用ins1() 函數(shù)。

  1. arguments: list object, where, new element 
  2.  
  3. returns: 0 if OK, -1 if not 
  4.  
  5. ins1: 
  6.  
  7.     resize list to size n+1 = 5 -> 4 more slots will be allocated 
  8.  
  9.     starting at the last element up to the offset whereright shift each element 
  10.  
  11.     set new element at offset where 
  12.  
  13.     return 0  

 

虛線的方框依舊表示已經(jīng)分配但沒有使用的槽空間?,F(xiàn)在分配了 8 個槽空間,但是列表的大小卻只是 5。

列表插入操作的平均復雜度為 O(n)。

Pop 操作

取出列表***一個元素 即l.pop(),調(diào)用了 listpop() 函數(shù)。在 listpop() 函數(shù)中會調(diào)用 list_resize 函數(shù),如果取出元素后列表的大小小于分配的槽空間數(shù)的一半,將會縮減列表的大小。

  1. arguments: list object 
  2.  
  3. returns: element popped 
  4.  
  5. listpop: 
  6.  
  7.     if list empty: 
  8.  
  9.         return null 
  10.  
  11.     resize list with size 5 - 1 = 4. 4 is not less than 8/2 so no shrinkage 
  12.  
  13.     set list object size to 4 
  14.  
  15.     return last element  

列表 pop 操作的平均復雜度為 O(1)。 

 

可以看到 pop 操作后槽空間 4 依然指向原先的整數(shù)對象,但是最為關鍵的是現(xiàn)在列表的大小已經(jīng)變?yōu)?4。

繼續(xù) pop 一個元素。在 list_resize() 函數(shù)中,size – 1 = 4 – 1 = 3 已經(jīng)小于所分配的槽空間大小的一半,所以縮減分配的槽空間為 6,同時現(xiàn)在列表的大小為 3。

可以看到槽空間 3 和 4 依然指向原先的整數(shù),但是現(xiàn)在列表的大小已經(jīng)變?yōu)?3。

 

Remove 操作

Python 的列表對象有個方法,刪除指定的元素: l.remove(5)。底層調(diào)用 listremove() 函數(shù)。

  1. arguments: list object, element to remove 
  2.  
  3. returns none if OK, null if not 
  4.  
  5. listremove: 
  6.  
  7.     loop through each list element: 
  8.  
  9.         if correct element: 
  10.  
  11.             slice list between element's slot and element's slot + 1 
  12.  
  13.             return none 
  14.  
  15.     return null  

為了做列表的切片并且刪除元素,調(diào)用了 list_ass_slice() 函數(shù),它的實現(xiàn)方法比較有趣。我們在刪除列表位置 1 的元素 5 的時候,低位的偏移量為 1 同時高位的偏移量為 2.

  1. arguments: list object, low offset, high offset 
  2.  
  3. returns: 0 if OK 
  4.  
  5. list_ass_slice: 
  6.  
  7.     copy integer 5 to recycle list to dereference it 
  8.  
  9.     shift elements from slot 2 to slot 1 
  10.  
  11.     resize list to 5 slots 
  12.  
  13.     return 0  

列表 remove 操作的復雜度為 O(n)。

 

責任編輯:龐桂玉 來源: Python開發(fā)者
相關推薦

2017-05-22 15:42:39

Python字典哈希表

2021-04-27 08:54:43

ConcurrentH數(shù)據(jù)結構JDK8

2010-07-13 10:13:35

Perl內(nèi)部函數(shù)

2025-04-07 11:10:00

Python列表開發(fā)

2021-09-03 09:55:43

架構Yarn內(nèi)部

2023-11-23 19:30:35

Python編程語言

2017-09-05 08:08:37

asyncio程序多線程

2010-09-25 15:59:54

JVM虛擬機

2021-08-19 16:56:37

Python內(nèi)存開發(fā)

2017-06-13 12:40:47

Python字符串對象

2014-04-23 14:40:06

iOS開發(fā)KVO內(nèi)部實現(xiàn)

2021-08-12 15:45:23

Pythonimport模塊

2016-10-20 08:46:17

2009-11-03 13:33:39

VB.NET對象列表

2022-10-26 15:22:31

React組件User組件

2015-07-28 10:06:03

C#內(nèi)部實現(xiàn)剖析

2024-07-05 10:47:15

2024-07-11 11:35:08

數(shù)組結構內(nèi)部機制

2010-03-05 13:38:13

Python數(shù)據(jù)轉(zhuǎn)換

2024-11-15 06:00:00

Python列表字典
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品99久久久久久宅男 | 中文字幕在线电影观看 | 亚欧性视频 | 华丽的挑战在线观看 | www.av在线| 精品国产一区二区在线 | 在线天堂免费中文字幕视频 | 欧美一级黄视频 | 美女久久久 | 偷拍自拍在线观看 | 精品免费在线 | 一级黄色片毛片 | 国产日韩欧美在线观看 | 成人av一区二区三区 | 免费在线一区二区三区 | 免费在线h视频 | 国产91丝袜在线播放 | 亚洲精品久久国产高清情趣图文 | 中文字幕成人在线 | av国产精品 | 婷婷久久五月 | 成人欧美一区二区三区黑人孕妇 | 亚洲视频国产视频 | 国产精品成人一区二区三区夜夜夜 | 国产不卡在线观看 | 福利片在线观看 | 日韩有码一区 | 成人在线视频观看 | 亚洲天堂中文字幕 | 老外黄色一级片 | 久草在线在线精品观看 | 日韩欧美一区二区三区免费观看 | 国产特级毛片aaaaaa喷潮 | 久久性色 | 久久久久久一区 | 国产精品精品视频一区二区三区 | 亚洲成av人片在线观看无码 | 久久国产精品99久久久久 | 黄色福利| 中文字幕一区二区在线观看 | 午夜免费网 |