日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

python列表和元組,到底用哪一個?

 

前面的課程,我們講解了 Python 語言的學習方法,并且帶你了解了 Python 必知的常用工具——Jupyter。那么從這節課開始,我們將正式學習 Python 的具體知識。

對于每一門編程語言來說,數據結構都是其根基。了解掌握 Python 的基本數據結構,對于學好這門語言至關重要。今天我們就一起來學習,Python 中最常見的兩種數據結構:列表(list)和元組(tuple)。

列表和元組基礎

首先,我們需要弄清楚最基本的概念,什么是列表和元組呢?

實際上,列表和元組,都是一個可以放置任意數據類型的有序集合

在絕大多數編程語言中,集合的數據類型必須一致。不過,對于 Python 的列表和元組來說,并無此要求:

l = [1, 2, 'hello', 'world'] # 列表中同時含有 int 和 string 類型的元素l[1, 2, 'hello', 'world'] tup = ('jason', 22) # 元組中同時含有 int 和 string 類型的元素tup('jason', 22)復制代碼

其次,我們必須掌握它們的區別。

  • 列表是動態的,長度大小不固定,可以隨意地增加、刪減或者改變元素(mutable)。
  • 而元組是靜態的,長度大小固定,無法增加刪減或者改變(immutable)。

下面的例子中,我們分別創建了一個列表與元組。你可以看到,對于列表,我們可以很輕松地讓其最后一個元素,由 4 變為 40;但是,如果你對元組采取相同的操作,Python 就會報錯,原因就是元組是不可變的。

l = [1, 2, 3, 4]l[3] = 40 # 和很多語言類似,python 中索引同樣從 0 開始,l[3] 表示訪問列表的第四個元素l[1, 2, 3, 40] tup = (1, 2, 3, 4)tup[3] = 40Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: 'tuple' object does not support item assignment復制代碼

可是,如果你想對已有的元組做任何"改變",該怎么辦呢?那就只能重新開辟一塊內存,創建新的元組了。

比如下面的例子,我們想增加一個元素 5 給元組,實際上就是創建了一個新的元組,然后把原來兩個元組的值依次填充進去。

而對于列表來說,由于其是動態的,我們只需簡單地在列表末尾,加入對應元素就可以了。如下操作后,會修改原來列表中的元素,而不會創建新的列表。

tup = (1, 2, 3, 4)new_tup = tup + (5, ) # 創建新的元組 new_tup,并依次填充原元組的值new _tup(1, 2, 3, 4, 5) l = [1, 2, 3, 4]l.Append(5) # 添加元素 5 到原列表的末尾l[1, 2, 3, 4, 5]復制代碼

通過上面的例子,相信你肯定掌握了列表和元組的基本概念。接下來我們來看一些列表和元組的基本操作和注意事項。

首先,和其他語言不同,Python 中的列表和元組都支持負數索引,-1 表示最后一個元素,-2 表示倒數第二個元素,以此類推。

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]] # 列表的每一個元素也是一個列表 tup = ((1, 2, 3), (4, 5, 6)) # 元組的每一個元素也是一元組復制代碼

當然,兩者也可以通過 list() 和 tuple() 函數相互轉換:

list((1, 2, 3))[1, 2, 3] tuple([1, 2, 3])(1, 2, 3)復制代碼

最后,我們來看一些列表和元組常用的內置函數:

l = [3, 2, 3, 7, 8, 1]l.count(3) 2l.index(7)3l.reverse()l[1, 8, 7, 3, 2, 3]l.sort()l[1, 2, 3, 3, 7, 8] tup = (3, 2, 3, 7, 8, 1)tup.count(3)2tup.index(7)3list(reversed(tup))[1, 8, 7, 3, 2, 3]sorted(tup)[1, 2, 3, 3, 7, 8]復制代碼

這里我簡單解釋一下這幾個函數的含義。

  • count(item) 表示統計列表 / 元組中 item 出現的次數。
  • index(item) 表示返回列表 / 元組中 item 第一次出現的索引。
  • list.reverse() 和 list.sort() 分別表示原地倒轉列表和排序(注意,元組沒有內置的這兩個函數)。
  • reversed() 和 sorted() 同樣表示對列表 / 元組進行倒轉和排序,但是會返回一個倒轉后或者排好序的新的列表 / 元組。

列表和元組存儲方式的差異

前面說了,列表和元組最重要的區別就是,列表是動態的、可變的,而元組是靜態的、不可變的。這樣的差異,勢必會影響兩者存儲方式。我們可以來看下面的例子:

l = [1, 2, 3]l.__sizeof__()64tup = (1, 2, 3)tup.__sizeof__()48 復制代碼

你可以看到,對列表和元組,我們放置了相同的元素,但是元組的存儲空間,卻比列表要少 16 字節。這是為什么呢?

事實上,由于列表是動態的,所以它需要存儲指針,來指向對應的元素(上述例子中,對于 int 型,8 字節)。另外,由于列表可變,所以需要額外存儲已經分配的長度大小(8 字節),這樣才可以實時追蹤列表空間的使用情況,當空間不足時,及時分配額外空間。

l = []l.__sizeof__() // 空列表的存儲空間為 40 字節40l.append(1)l.__sizeof__() 72 // 加入了元素 1 之后,列表為其分配了可以存儲 4 個元素的空間 (72 - 40)/8 = 4l.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: 9.97 nsec per looppython3 -m timeit 'x=[1,2,3,4,5,6]'5000000 loops, best of 5: 50.1 nsec per loop復制代碼

但如果是索引操作的話,兩者的速度差別非常小,幾乎可以忽略不計。

python3 -m timeit -s 'x=[1,2,3,4,5,6]' 'y=x[3]'10000000 loops, best of 5: 22.2 nsec per looppython3 -m timeit -s 'x=(1,2,3,4,5,6)' 'y=x[3]'10000000 loops, best of 5: 21.9 nsec per loop復制代碼

當然,如果你想要增加、刪減或者改變元素,那么列表顯然更優。原因你現在肯定知道了,那就是對于元組,你必須得通過新建一個元組來完成。

列表和元組的使用場景

那么列表和元組到底用哪一個呢?根據上面所說的特性,我們具體情況具體分析。

1. 如果存儲的數據和數量不變,比如你有一個函數,需要返回的是一個地點的經緯度,然后直接傳給前端渲染,那么肯定選用元組更合適。

def get_location():    .....     return (longitude, latitude)復制代碼

2. 如果存儲的數據或數量是可變的,比如社交平臺上的一個日志功能,是統計一個用戶在一周之內看了哪些用戶的帖子,那么則用列表更合適。

viewer_owner_id_list = [] # 里面的每個元素記錄了這個 viewer 一周內看過的所有 owner 的 idrecords = queryDB(viewer_id) # 索引數據庫,拿到某個 viewer 一周內的日志for record in records:    viewer_owner_id_list.append(record.id)復制代碼

總結

關于列表和元組,我們今天聊了很多,最后一起總結一下你必須掌握的內容。

總的來說,列表和元組都是有序的,可以存儲任意數據類型的集合,區別主要在于下面這兩點。

  • 列表是動態的,長度可變,可以隨意的增加、刪減或改變元素。列表的存儲空間略大于元組,性能略遜于元組。
  • 元組是靜態的,長度大小固定,不可以對元素進行增加、刪減或者改變操作。元組相對于列表更加輕量級,性能稍優。

思考題

1. 想創建一個空的列表,我們可以用下面的 A、B 兩種方式,請問它們在效率上有什么區別嗎?我們應該優先考慮使用哪種呢?可以說說你的理由。

# 創建空列表# option Aempty_list = list() # option Bempty_list = []復制代碼

2. 你在平時的學習工作中,是在什么場景下使用列表或者元組呢?歡迎留言和我分享。

分享到:
標簽:列表 python
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定