Python進階之路(四)你所不知道的列表

Python 數據結構 編譯器 設計 EchoPython 2019-07-10

1.列表概述

僅僅從操作方式上看,列表像是數組和鏈表的結合體,除按照索引訪問外,還支持插入,追加,刪除等操作.完全可當做隊列或者棧進行使用.如果不考慮性能問題,列表視乎是一種易用且功能完善的理想數據結構.

```python

In [1]: x= [1, 2]

In [2]: x[1]

Out[2]: 2

In [3]: x.insert(0,0) # 插入數據

In [4]: x

Out[4]: [0, 1, 2]

In [5]: x.reverse() # 反轉

In [6]: x

Out[6]: [2, 1, 0]

```

queue

```python

In [7]: q = []

In [8]: q.append(1) # 在列表最後插入一個數據

In [9]: q.append(2)

In [10]: q

Out[10]: [1, 2]

In [11]: q.pop() # 清除追加順序彈出數據

Out[11]: 2

In [12]: q.pop()

Out[12]: 1

In [13]: q

Out[13]: []

```

***

如果有大量寫操作,建議使用 collections,queue 類型

***

列表的內部結構是由兩部分組成,保存元素數量和內存分配計數的頭部,以及儲存元素指針的獨立數組.所有元素項使用該數組保存指針引用,並不嵌入內容.

Python進階之路(四)你所不知道的列表

***

作為使用頻率最高的數據結構之一,列表的性能優化很重要,固定長度的頭部結構,很容易實現內存複用.創建時,有限從複用區獲取.被揮手時,除非超出複用數量限制(80) ,否則會被放回服用去,而非交還內存,每次真正需要分配和釋放的是指針數組.

用數組而非鏈表存儲元素項引用,也有實際考慮.從讀操作開看,無論遍歷還是基於序號訪問,數組性能總是最高的.儘管插入,刪除,等變更操作需要移動內存,但也僅僅是指針複製,無論元素大小,不會有太高消耗,如果列表太大,或者寫操作多餘讀,那麼應該使用針對性的數據結構操作.

***

2.構建

顯示指定元素構建語法最為常用,也可基於創建類型,接受可迭代對象作為初始內容,不同於數組,列表僅存儲指針,而對元素內容毫不關心,如此,可以是不同類型混合.

```python

In [14]: [1,"abc",3.14]

Out[14]: [1, 'abc', 3.14]

In [16]: list("abc")

Out[16]: ['a', 'b', 'c']

In [17]: list(range(3))

Out[17]: [0, 1, 2]

```

另外有被稱之為列表推導式的語法,同樣適用括號,但是以for循環初始化元素,並且可以選擇if作為過濾條件.

```python

In [1]: class A(list):

...: pass

...:

In [2]: type(A('abc')+ list('del')) # 返回的是list而不是a

Out[2]: list

In [3]: class B(collections.UserList):

...: pass

In [4]: type(B("abc") + list("del")) # 返回了B類型

Out[4]: __main__.B

```

***

最小接口設計是一個基本原則,應該慎重考慮這種功能的類型是否適合作為基類.

3.操作

用加法運算符鏈接多個列表,乘法賦值內容

```python

In [9]: [1, 2] + [3, 4]

Out[9]: [1, 2, 3, 4]

In [10]: [1, 2] * 2

Out[10]: [1, 2, 1, 2]

```

注意,同時加法(或者減法) 運算,但是結果可能會不同.

```python

In [12]: a = [1, 2]

In [13]: b = a

In [14]: a = a + [3, 4] # 新建列表對象,然後和a關聯

In [15]: a

Out[15]: [1, 2, 3, 4] # a,b結果不同,確定a指向新對象

In [16]: b

Out[16]: [1, 2]

In [17]: a = [1, 2]

In [18]: b = a

In [19]: a += [3, 4] # 直接修改了a的內容

In [20]: a

Out[20]: [1, 2, 3, 4]

In [21]: b # b的內容也隨著更改

Out[21]: [1, 2, 3, 4]

```

> 編譯器將"+=" 運算符處理成INPLACE_ADD操作,也就是修改原函數,而並非建立新對象,其中效果類似於list.extend 方法

判斷元素是否存在,習慣用in,而並非index()方法

```python

in[22]: 2 in [1, 2]

Out[22]: True

```

至於刪除操作,可用索引序號指定單個元素,或者切片指定刪除範圍.

```python

In [23]: a = [0, 1, 2, 3, 4, 5]

In [24]: del a[5] # 刪除單個元素

In [25]: a

Out[25]: [0, 1, 2, 3, 4]

In [26]: del a[1:2] # 刪除範圍元素

In [27]: a

Out[27]: [0, 2, 3, 4]

```

返回切片時創建新列表對象,並且複製相關指針數據到新數組,出所引用目標相同之外,列表自身的修改(增加,刪除) 互不影響

```python

In [32]: a = [0, 2, 4 ,6]

In [33]: b = a[:2] # 複製引用

In [34]: b

Out[34]: [0, 2]

In [35]: a[0] is b[0]

Out[35]: True

In [36]: a.insert(1,1) # 對a列表操作,不會影響b

In [37]: a

Out[37]: [0, 1, 2, 4, 6]

In [38]: b

Out[38]: [0, 2]

```

***

複製的是指針(引用),而並非目標元素對象.

對列表自身的修改互補影響,但是對目標元素對象的修改是共享的

***

### 3.列表排序可以設定條件,比如按照字段或者長度等

```python

In [55]: d = [3,0,2,1]

In [56]: sorted(d) # 同樣可以指定排序條件,或者倒敘

Out[56]: [0, 1, 2, 3]

In [57]: d

Out[57]: [3, 0, 2, 1]

```

4.利用bisect模塊,可向有序列表插入元素,它使用二分法查找合適位置,可以實現優先級隊列或者一致性哈希算法

```python

In [59]: import bisect

In [60]: bisect.insort_left(d,1) # 插入新的元素後,依舊保持有序狀態

In [61]: d

Out[61]: [0, 1, 2, 4]

In [62]: bisect.insort_left(d,2)

In [63]: d

Out[63]: [0, 1, 2, 2, 4]

In [64]: bisect.insort_left(d,3)

In [65]: d

Out[65]: [0, 1, 2, 2, 3, 4]

```

自定義複合類型,可通過重載比較運算符(__eq__,__lt__ 等) 實現自定義排序條件.

文章的最後呢:

最後小編我自己是一名高級python開發工程師,這裡有我自己整理了一套最新的python系統學習教程,包括從基礎的python基礎到web開發、爬蟲、數據分析、數據可視化、機器學習,自動化運維,Linux系統學習等。想要這些資料的可以關注小編,並在後臺私信小編:“01”即可領取。

最後謝謝各位大佬閱讀到現在,萬分感謝

相關推薦

推薦中...