[Python進階] 1. 列表與元組
一、基礎知識
- 列表和元組,都是一個可以放置任意數據類型的有序集合,列表或元組中的元素數據類型不需要保持一致。
- 列表是
mutable
而元組是immutable
。 - Python中的列表和元組都支持負數索引,-1表示最後一個元素。
- 列表和元組都支持切片操作,且都可以隨意嵌套。
- 兩者可以通過
list()
和tuple()
函數相互轉換。
列表和元組常用的內置函數
count(item)
表示統計列表 / 元組中 item
出現的次數。
index(item)
表示返回列表 / 元組中 item
第一次出現的索引。
list.reverse()
和 list.sort()
分別表示原地倒轉列表和排序(注意,元組沒有內置的這兩個函數)。
reversed()
和 sorted()
同樣表示對列表 / 元組進行倒轉和排序,但是會返回一個倒轉後或者排好序的新的列表 / 元組。
二、列表和元組的存儲方式
>>> l = [1, 2, 3]
>>> l.__sizeof__()
64
>>> tup = (1, 2, 3)
>>> tup.__sizeof__()
48
上面結果表明對於相同元素的元組與列表,元組的存儲空間比列表要少 16 字節。
- 由於列表是動態的,所以它需要存儲指針,來指向對應的元素,int型指針佔8個字節。
- 由於列表可變,所以需要額外存儲已經分配的長度大小(8 字節),這樣纔可以實時追蹤列表空間的使用情況,當空間不足時,及時分配額外空間。
>>> l = []
>>> l.__sizeof__() #空列表的存儲空間爲 40 字節
40
>>> l.append(1)
>>> l.__sizeof__()
72 #加入了元素 1 之後,列表爲其分配了可以存儲 4 個元素的空間 (72 - 40)/8 = 4
>>> l.append(2)
>>> l.__sizeof__()
72 #由於之前分配了空間,所以加入元素 2,列表空間不變
>>> l.append(3)
>>> l.__sizeof__()
72
>>> l.append(4)
>>> l.__sizeof__()
72
>>> l.append(5)
>>> l.__sizeof__()
104 #加入元素5之後,列表的空間不足,所以又額外分配了可以存儲 4 個元素的空間
列表空間分配:爲了減小每次增加 / 刪減操作時空間分配的開銷,Python 每次分配空間時都會額外多分配一些,這樣的機制 (over-allocating)保證了其操作的高效性:增加 / 刪除的時間複雜度均爲 O(1)。
三、列表和元組的性能
由存儲方式的區別可以得出結論:元組要比列表更加輕量級一些,所以總體上來說,元組的性能速度要略優於列表。
Python 會在後臺,對靜態數據做一些資源緩存(resource caching)。通常來說, 因爲垃圾回收機制的存在,如果一些變量不被使用了,Python 就會回收它們所佔用的內存,返還給操作系統,以便其他變量或其他應用使用。
但是對於一些靜態變量,比如元組,如果它不被使用並且佔用空間不大時,Python 會暫時緩存這部分內存。這樣,下次我們再創建同樣大小的元組時,Python 就可以不用再向操作系統發出請求,去尋找內存,而是可以直接分配之前緩存的內存空間,這樣就能大大加快程序的運行速度。
-
計算初始化一個相同元素的列表和元組分別所需的時間。可以看到,元組的初始化速度,要比列表快 5 倍。
python3 -m timeit 'x=(1,2,3,4,5,6)' 20000000 loops, best of 5: 13.5 nsec per loop python3 -m timeit 'x=[1,2,3,4,5,6]' 5000000 loops, best of 5: 67.7 nsec per loop
-
如果是索引操作的話,兩者的速度差別非常小,幾乎可以忽略不計。
python3 -m timeit -s 'x=[1,2,3,4,5,6]' 'y=x[3]' 10000000 loops, best of 5: 30.1 nsec per loop python3 -m timeit -s 'x=(1,2,3,4,5,6)' 'y=x[3]' 10000000 loops, best of 5: 30.2 nsec per loop
-
如果增加、刪減或者改變元素,那麼顯然列表更優,因爲元組要重新開闢內存空間。
四、列表和元組的使用場景
- 元組適用於存儲的數據和數量不變。
- 列表適用於存儲的數據或數量是可變的。
五、總結
列表是動態的,長度可變,可以隨意的增加、刪減或改變元素。列表的存儲空間略大於元組,性能略遜於元組。
元組是靜態的,長度大小固定,不可以對元素進行增加、刪減或者改變操作。元組相對於列表更加輕量級,性能稍優。