列表和元組基礎
列表和元組都是一個可以放置任意數據類型的有序集合
# 可以包含所有的數據類型
lst = ['hello', 123, [1,2], {1:2}] tup = ('hello', 123, [1,2], {1:2})
列表是動態的, 長度大小不固定, 可以隨意的增加、刪除或者該表元素(mutable)
元組是靜態的, 長度大小固定, 無法增加刪減或者改變(immutable)
lst = ['hello', 123, [1,2], {1:2}] tup = ('hello', 123, [1,2], {1:2}) # 可以正常的修改數據
lst[1] = 456 print(lst) ['hello', 456, [1, 2], {1: 2}]
# 元組是不可變的, 做修改的話會報錯
# 如果想對已有的元組做任何'改變', 那就只能重新開辟一塊內存,創建新元組 tup[1] = 456 print(tup) Traceback (most recent call last): File "E:/Python/review/list_and_tuple.py", line 7, in <module> dup[1] = 456 TypeError: 'tuple' object does not support item assignment
lst = ['hello', 123, [1,2], {1:2}] tup = ('hello', 123, [1,2], {1:2}) # 列表只是添加到原列表末尾
print(id(lst)) # 23153240 lst.append('456') print(id(lst)) # 23153240 # 元組做修改會重新開辟一塊空間, 實際上就是創建一個新元組
print(id(tup)) # 52580096 tup = tup + ('456',) print(id(tup)) # 52579232
元組和列表都支持索引和負索引
lst = ['hello', 123, [1,2], {1:2}] tup = ('hello', 123, [1,2], {1:2}) print(lst[2]) # [1, 2] print(tup[2]) # [1, 2] print(lst[-1]) # {1: 2} print(tup[-1]) # {1: 2}
元組和列表都支持切片操作,[開始索引, 結束索引, 步長] 步長為負反轉
lst = ['hello', 123, [1,2], {1:2}] tup = ('hello', 123, [1,2], {1:2}) print(lst[1:3]) # [123, [1, 2]] print(tup[1:3]) # (123, [1, 2]) print(lst[::-2]) # [{1: 2}, [1, 2], 123, 'hello'] print(tup[::-1]) # ({1: 2}, 123)
列表和元組可以互相轉換
lst = ['hello', 123, [1,2], {1:2}] tup = ('hello', 123, [1,2], {1:2}) print(tuple(lst)) # ('hello', 123, [1, 2], {1: 2}) print(list(tup)) # ['hello', 123, [1, 2], {1: 2}]
列表和元組存儲方式的差異
列表是動態的, 所以需要存儲指針, 來指向對應的元素, 由於列表是可變的, 所以需要額外存儲已經分配的長度大小, 這樣才可以實時追蹤列表空間的使用情況, 當空間不足時, 及時分配額外空間
lst = [] tup = () print(lst.__sizeof__()) # 20 print(tup.__sizeof__()) # 12 lst.append(1) tup = tup + (1,) print(lst.__sizeof__()) # 36 當空間不足, 列表為其分配了4個元素的空間 print(tup.__sizeof__()) # 16 每次增加4個字節 lst.append(2) tup = tup + (2,) print(lst.__sizeof__()) # 36 之前分配了空間, 所以列表空間不變 print(tup.__sizeof__()) # 20 同上 lst.append(3) tup = tup + (3,) print(lst.__sizeof__()) # 36 同上 print(tup.__sizeof__()) # 24 同上 lst.append(4) tup = tup + (4,) print(lst.__sizeof__()) # 36 同上 print(tup.__sizeof__()) # 28 同上 lst.append(5) tup = tup + (5,) print(lst.__sizeof__()) # 52 空間再次不足, 列表再次為其分配了4個元素的空間 print(tup.__sizeof__()) # 32 同上
列表: Python每次分配空間是都會額外多分配一些, 這樣的機制保證了其操作的高效性: 增加/刪除的時間復雜度均為O(1)
元組: 長度大小固定, 元素不可變, 所以存儲空間不變
在數據較小的時候, 差異可以忽略不計, 但是如果數據是上億以上, 那么就不能忽略了
列表和元組的性能
元組要比列表更加輕量級一些, 所以總體來說, 元組的性能速度要略優於列表
Python會在后台, 對靜態數據做一些資源緩存, 通常來說因為垃圾回收機制的存在, 如果一些變量不被使用了, Python就會回收它們所占用的內存, 返還給操作系統, 以便其他變量或其他應用使用
但是對於一些靜態變量, 比如元組, 如果他不被使用並且空間不大時, Python會暫時緩存這部分內存, 這樣, 下次我們在創建同樣大小的元組是, Python就可以不用再想操作系統發出請求, 去尋找內存, 而是可以直接分配緩存的內存空間, 這樣就能大大加快程序的運行速度
python3 -m timeit (1,2,3,4,5,6) 20000000 loops, best of 5: 11.9 nsec per loop python3 -m timeit [1,2,3,4,5,6] 5000000 loops, best of 5: 86 nsec per loop
但如果索引操作的話, 兩者的速度差別非常小, 幾乎可以忽略不計
如果想要增加、刪減或者改變元素, 那么列表顯然更優, 因為元組必須通過新建一個元組來完成
列表和元組的使用場景
如果存儲的數據和數量不變, 比如你有一個函數, 需要返回的是一個地點的經緯度, 然后直接傳給前端渲染, 那么肯定選用元組更合適
如果存儲的數據或數量是可變的, 比如社交平台上的一個日志功能, 是統計一個用戶在一周之內看了哪些用戶的帖子, 那么則用列表更合適
列表內置函數
長度len
len(list) 返回列表的長度
in 與 not in
in 判斷元素是否在列表中
not in 判斷元素是否不在列表中
循環 for
for i in list: print(i)
追加 append
list.append(n) 在列表的最后追加n
按索引添加 insert
list.insert(n,m) 在第n個元素的位置添加m
追加一個列表 extend
list.extend([1,2,3]) 在列表的末尾一次型追加立一個序列(原組和列表)中的多個值(用新列表擴展原來的列表)
按索引刪除 del
del list[n] n為列表的索引
按元素刪除 remove
list.remove(n) n為列表的元素
隨機移除 pop
list.pop(1) 移除列表中的某個元素,並返回該院屬的值
最大值 max
max(list) 返回列表中的最大值
最小值 min
min(list) 返回列表中的最小值
統計次數 count
list.count(n) n為列表中的元素
排序 sort
list.sort() 對列表按照大小排序 reverse=True 參數 反向排序
反轉 reverse
list.reverse()
元組內置函數
長度len
len(tuple) 返回元組的長度
in 與 not in
in 判斷元素是否在元組中
not in 判斷元素是否不在元組中
循環 for
for i in tuple: print(i)
最大值 max
max(tuple)
最小值 min
min(tuple)
總結
總的來說, 列表和元組都是有序的, 可以存儲任意數據類型的集合, 區別主要在於下面的兩點
1. 列表是動態的, 長度可變, 可以隨意的增加、刪減或改變元素, 列表的存儲空間略大於元組, 性能略差與元組
2. 元組是靜態的, 長度大小固定, 不可以對元素進行增加、刪減或改變操作, 元組相對於列表更加輕量級, 性能稍優