列表和元組基礎(chǔ)
概念
列表和元組,都是一個(gè)可以放置任意數(shù)據(jù)類型的有序集合。
在絕大多數(shù)編程語言中,集合的數(shù)據(jù)類型必須一致。不過,對(duì)于 Python 的列表和元組來 說,并無此要求:
l = [1, 2, 'hello', 'world'] # 列表中同時(shí)含有 int 和 string 類型的元素
l
[1, 2, 'hello', 'world']
tup = ('jason', 22) # 元組中同時(shí)含有 int 和 string 類型的元素
tup
('jason', 22)
區(qū)別
列表是動(dòng)態(tài)的,長(zhǎng)度大小不固定,可以隨意地增加、刪減或者改變?cè)兀╩utable)。
而元組是靜態(tài)的,長(zhǎng)度大小固定,無法增加刪減或者改變(immutable)。
如何改變?cè)M?
重新開辟一塊內(nèi)存,創(chuàng)建新的元組
tup = (1, 2, 3, 4)
new_tup = tup + (5, ) # 創(chuàng)建新的元組 new_tup,并依次填充原元組的值
new _tup
(1, 2, 3, 4, 5)
列表和元組的基礎(chǔ)操作和注意事項(xiàng)
- 都支持負(fù)數(shù)索引,1 表示最后一個(gè)元 素,-2 表示倒數(shù)第二個(gè)元素,以此類推。
l = [1, 2, 3, 4]
l[-1]
4
tup = (1, 2, 3, 4)
tup[-1]
4
- 都支持切片(遵循顧前不顧后原則)
l = [1, 2, 3, 4]
l[1:3] # 返回列表中索引從 1 到 2 的子列表
[2, 3]
tup = (1, 2, 3, 4)
tup[1:3] # 返回元組中索引從 1 到 2 的子元組
(2, 3)
- 都可以嵌套
l = [[1, 2, 3], [4, 5],(4,7),{"a":1}] # 列表的每一個(gè)元素也是一個(gè)列表,也可以嵌套dict、tuple
tup = ((1, 2, 3), (4, 5, 6)) # 元組的每一個(gè)元素也是一元組
- 轉(zhuǎn)換類型
list((1, 2, 3))
[1, 2, 3]
tuple([1, 2, 3])
(1, 2, 3)
- 內(nèi)置函數(shù)
列表和元組存儲(chǔ)方式的差異
列表和元組最重要的區(qū)別就是,列表是動(dòng)態(tài)的、可變的,而元組是靜態(tài)的、不可 變的。這樣的差異,勢(shì)必會(huì)影響兩者存儲(chǔ)方式。我們可以來看下面的例子:
l = [1, 2, 3]
l.__sizeof__()
64
tup = (1, 2, 3)
tup.__sizeof__()
48
為什么列表要比元組的存儲(chǔ)空間多16字節(jié)?
由于列表是動(dòng)態(tài)的,所以它需要存儲(chǔ)指針,來指向?qū)?yīng)的元素(上述例子中,對(duì)于 int 型,8 字節(jié))。另外,由于列表可變,所以需要額外存儲(chǔ)已經(jīng)分配的長(zhǎng)度大?。? 字 節(jié)),這樣才可以實(shí)時(shí)追蹤列表空間的使用情況,當(dāng)空間不足時(shí),及時(shí)分配額外空間。
上面的例子,大概描述了列表空間分配的過程。我們可以看到,為了減小每次增加 / 刪減 操作時(shí)空間分配的開銷,Python 每次分配空間時(shí)都會(huì)額外多分配一些,這樣的機(jī)制 (over-allocating)保證了其操作的高效性:增加 / 刪除的時(shí)間復(fù)雜度均為 O(1)。
但是對(duì)于元組,情況就不同了。元組長(zhǎng)度大小固定,元素不可變,所以存儲(chǔ)空間固定。
列表和元組的性能
通過學(xué)習(xí)列表和元組存儲(chǔ)方式的差異,我們可以得出結(jié)論:元組要比列表更加輕量級(jí)一些, 所以總體上來說,元組的性能速度要略優(yōu)于列表。
另外,Python 會(huì)在后臺(tái),對(duì)靜態(tài)數(shù)據(jù)做一些資源緩存(resource caching)。通常來說, 因?yàn)槔厥諜C(jī)制的存在,如果一些變量不被使用了,Python 就會(huì)回收它們所占用的內(nèi)存,返還給操作系統(tǒng),以便其他變量或其他應(yīng)用使用。
但是對(duì)于一些靜態(tài)變量,比如元組,如果它不被使用并且占用空間不大時(shí),Python 會(huì)暫時(shí) 緩存這部分內(nèi)存。這樣,下次我們?cè)賱?chuàng)建同樣大小的元組時(shí),Python 就可以不用再向操作 系統(tǒng)發(fā)出請(qǐng)求,去尋找內(nèi)存,而是可以直接分配之前緩存的內(nèi)存空間,這樣就能大大加快程 序的運(yùn)行速度。
下面的例子,是計(jì)算初始化一個(gè)相同元素的列表和元組分別所需的時(shí)間。我們可以看到,元 組的初始化速度,要比列表快 5 倍。
python3 -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
python3 -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loo
但如果是索引操作的話,兩者的速度差別非常小,幾乎可以忽略不計(jì)。
python3 -m timeit -s 'x=[1,2,3,4,5,6]' 'y=x[3]'
10000000 loops, best of 5: 22.2 nsec per loop
python3 -m timeit -s 'x=(1,2,3,4,5,6)' 'y=x[3]'
10000000 loops, best of 5: 21.9 nsec per loo
當(dāng)然,如果你想要增加、刪減或者改變?cè)?,那么列表顯然更優(yōu)。原因你現(xiàn)在肯定知道了, 那就是對(duì)于元組,你必須得通過新建一個(gè)元組來完成。
列表和元組的使用場(chǎng)景
- 如果存儲(chǔ)的數(shù)據(jù)和數(shù)量不變,比如你有一個(gè)函數(shù),需要返回的是一個(gè)地點(diǎn)的經(jīng)緯度,然 后直接傳給前端渲染,那么肯定選用元組更合適。
- 如果存儲(chǔ)的數(shù)據(jù)或數(shù)量是可變的,比如社交平臺(tái)上的一個(gè)日志功能,是統(tǒng)計(jì)一個(gè)用戶在 一周之內(nèi)看了哪些用戶的帖子,那么則用列表更合適。
總結(jié)
關(guān)于列表和元組,我們今天聊了很多,最后一起總結(jié)一下你必須掌握的內(nèi)容。
總的來說,列表和元組都是有序的,可以存儲(chǔ)任意數(shù)據(jù)類型的集合,區(qū)別主要在于下面這兩點(diǎn)。
- 列表是動(dòng)態(tài)的,長(zhǎng)度可變,可以隨意的增加、刪減或改變?cè)?。列表的存?chǔ)空間略大于元組,性能略遜于元組。
- 元組是靜態(tài)的,長(zhǎng)度大小固定,不可以對(duì)元素進(jìn)行增加、刪減或者改變操作。元組相對(duì)于 列表更加輕量級(jí),性能稍優(yōu)。
思考題
想創(chuàng)建一個(gè)空的列表,我們可以用下面的 A、B 兩種方式,請(qǐng)問它們?cè)谛噬嫌惺裁磪^(qū) 別嗎?我們應(yīng)該優(yōu)先考慮使用哪種呢?可以說說你的理由。
# 創(chuàng)建空列表
# option A
empty_list = list()
# option B
empty_list = []
區(qū)別主要在于list()是一個(gè)function call,Python的function call會(huì)創(chuàng)建stack,并且進(jìn)行一系列參 數(shù)檢查的操作,比較expensive,反觀[]是一個(gè)內(nèi)置的C函數(shù),可以直接被調(diào)用,因此效率高。文章來源:http://www.zghlxwxcb.cn/news/detail-475908.html
另外, list和tuple的內(nèi)部實(shí)現(xiàn)都是array的形式,list因?yàn)榭勺?,所以是一個(gè)over-allocate的 array,tuple因?yàn)椴豢勺?,所以長(zhǎng)度大小固定文章來源地址http://www.zghlxwxcb.cn/news/detail-475908.html
到了這里,關(guān)于【學(xué)習(xí)筆記】Python核心技術(shù)與實(shí)戰(zhàn)-基礎(chǔ)篇-03列表和元組,到底用哪個(gè)?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!