Python元組和列表的區別

2020-07-16 10:05:05
元組和列表同屬序列型別,且都可以按照特定順序存放一組資料,資料型別不受限制,只要是 Python 支援的資料型別就可以。那麼,元組和列表有哪些區別呢?

元組和列表最大的區別就是,列表中的元素可以進行任意修改,就好比是用鉛筆在紙上寫的字,寫錯了還可以擦除重寫;而元組中的元素無法修改,除非將元組整體替換掉,就好比是用圓珠筆寫的字,寫了就擦不掉了,除非換一張紙。

可以理解為,tuple 元組是一個唯讀版本的 list 列表。

需要注意的是,這樣的差異勢必會影響兩者的儲存方式,我們來直接看下面的例子:

>>> listdemo = []
>>> listdemo.__sizeof__()
40
>>> tupleDemo = ()
>>> tupleDemo.__sizeof__()
24

可以看到,對於列表和元組來說,雖然它們都是空的,但元組卻比列表少占用 16 個位元組,這是為什麼呢?

事實上,就是由於列表是動態的,它需要儲存指標來指向對應的元素(占用 8 個位元組)。另外,由於列表中元素可變,所以需要額外儲存已經分配的長度大小(占用 8 個位元組)。但是對於元組,情況就不同了,元組長度大小固定,且儲存元素不可變,所以儲存空間也是固定的。

讀者可能會問題,既然列表這麼強大,還要元組這種序列型別幹什麼?

通過對比列表和元組儲存方式的差異,我們可以引申出這樣的結論,即元組要比列表更加輕量級,所以從總體上來說,元組的效能速度要由於列表。

另外,Python 會在後台,對靜態資料做一些資源快取。通常來說,因為垃圾回收機制的存在,如果一些變數不被使用了,Python 就會回收它們所佔用的記憶體,返還給作業系統,以便其他變數或其他應用使用。

但是對於一些靜態變數(比如元組),如果它不被使用並且佔用空間不大時,Python 會暫時快取這部分記憶體。這樣的話,當下次再建立同樣大小的元組時,Python 就可以不用再向作業系統發出請求去尋找記憶體,而是可以直接分配之前快取的記憶體空間,這樣就能大大加快程式的執行速度。

下面的例子,是計算初始化一個相同元素的列表和元組分別所需的時間。我們可以看到,元組的初始化速度要比列表快 5 倍。

C:Usersmengma>python -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
C:Usersmengma>python -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loop

當然,如果你想要增加、刪減或者改變元素,那麼列表顯然更優。因為對於元組來說,必須得通過新建一個元組來完成。

總的來說,元組確實沒有列表那麼多功能,但是元組依舊是很重要的序列型別之一,元組的不可替代性體現在以下這些場景中:
  1. 元組作為很多內建函數和序列型別方法的返回值存在,也就是說,在使用某些函數或者方法時,它的返回值會元組型別,因此你必須對元組進行處理。
  2. 元組比列表的存取和處理速度更快,因此,當需要對指定元素進行存取,且不涉及修改元素的操作時,建議使用元組。
  3. 元組可以在對映(和集合的成員)中當做“鍵”使用,而列表不行。這會在後續章節中作詳解介紹。