Python常用數(shù)據(jù)類型之列表使用詳解
1.常用數(shù)據(jù)結(jié)構(gòu)之列表
我們先給大家一個(gè)編程任務(wù),將一顆色子擲6000次,統(tǒng)計(jì)每個(gè)點(diǎn)數(shù)出現(xiàn)的次數(shù)。這個(gè)任務(wù)對(duì)大家來說應(yīng)該是非常簡單的,我們可以用1到6均勻分布的隨機(jī)數(shù)來模擬擲色子,然后用6個(gè)變量分別記錄每個(gè)點(diǎn)數(shù)出現(xiàn)的次數(shù),相信大家都能寫出下面的代碼。
import random f1 = 0 f2 = 0 f3 = 0 f4 = 0 f5 = 0 f6 = 0 for _ in range(6000): face = random.randint(1, 6) if face == 1: f1 += 1 elif face == 2: f2 += 1 elif face == 3: f3 += 1 elif face == 4: f4 += 1 elif face == 5: f5 += 1 else: f6 += 1 print(f'1點(diǎn)出現(xiàn)了{(lán)f1}次') print(f'2點(diǎn)出現(xiàn)了{(lán)f2}次') print(f'3點(diǎn)出現(xiàn)了{(lán)f3}次') print(f'4點(diǎn)出現(xiàn)了{(lán)f4}次') print(f'5點(diǎn)出現(xiàn)了{(lán)f5}次') print(f'6點(diǎn)出現(xiàn)了{(lán)f6}次')
看看上面的代碼,相信大家一定覺得它非常的“笨重”和“丑陋”,更可怕的是,如果要統(tǒng)計(jì)擲兩顆或者更多的色子統(tǒng)計(jì)每個(gè)點(diǎn)數(shù)出現(xiàn)的次數(shù),那就需要定義更多的變量,寫更多的分支結(jié)構(gòu)。講到這里,相信大家一定想問:有沒有辦法用一個(gè)變量來保存多個(gè)數(shù)據(jù),有沒有辦法用統(tǒng)一的代碼對(duì)多個(gè)數(shù)據(jù)進(jìn)行操作?答案是肯定的,在Python中我們可以通過容器類型的變量來保存和操作多個(gè)數(shù)據(jù),我們首先為大家介紹列表(list)這種新的數(shù)據(jù)類型。
2.定義和使用列表
在Python中,列表是由一系元素按特定順序構(gòu)成的數(shù)據(jù)序列,這樣就意味著定義一個(gè)列表類型的變量,可以保存多個(gè)數(shù)據(jù),而且允許有重復(fù)的數(shù)據(jù)。跟上一課我們講到的字符串類型一樣,列表也是一種結(jié)構(gòu)化的、非標(biāo)量類型,操作一個(gè)列表類型的變量,除了可以使用運(yùn)算符還可以使用它的方法。
在Python中,可以使用[]字面量語法來定義列表,列表中的多個(gè)元素用逗號(hào)進(jìn)行分隔,代碼如下所示。
items1 = [35, 12, 99, 68, 55, 87] items2 = ['Python', 'Java', 'Go', 'Kotlin']
除此以外,還可以通過Python內(nèi)置的list函數(shù)將其他序列變成列表。準(zhǔn)確的說,list并不是一個(gè)普通的函數(shù),它是創(chuàng)建列表對(duì)象的構(gòu)造器(后面會(huì)講到對(duì)象和構(gòu)造器這兩個(gè)概念)。
items1 = list(range(1, 10)) print(items1) # [1, 2, 3, 4, 5, 6, 7, 8, 9] items2 = list('hello') print(items2) # ['h', 'e', 'l', 'l', 'o']
需要說明的是,列表是一種可變數(shù)據(jù)類型,也就是說列表可以添加元素、刪除元素、更新元素,這一點(diǎn)跟我們上一課講到的字符串有著鮮明的差別。字符串是一種不可變數(shù)據(jù)類型,也就是說對(duì)字符串做拼接、重復(fù)、轉(zhuǎn)換大小寫、修剪空格等操作的時(shí)候會(huì)產(chǎn)生新的字符串,原來的字符串并沒有發(fā)生任何改變。
2.1列表的運(yùn)算符
和字符串類型一樣,列表也支持拼接、重復(fù)、成員運(yùn)算、索引和切片以及比較運(yùn)算,對(duì)此我們不再進(jìn)行贅述,請(qǐng)大家參考下面的代碼。
items1 = [35, 12, 99, 68, 55, 87] items2 = [45, 8, 29] # 列表的拼接 items3 = items1 + items2 print(items3) # [35, 12, 99, 68, 55, 87, 45, 8, 29] # 列表的重復(fù) items4 = ['hello'] * 3 print(items4) # ['hello', 'hello', 'hello'] # 列表的成員運(yùn)算 print(100 in items3) # False print('hello' in items4) # True # 獲取列表的長度(元素個(gè)數(shù)) size = len(items3) print(size) # 9 # 列表的索引 print(items3[0], items3[-size]) # 35 35 items3[-1] = 100 print(items3[size - 1], items3[-1]) # 100 100 # 列表的切片 print(items3[:5]) # [35, 12, 99, 68, 55] print(items3[4:]) # [55, 87, 45, 8, 100] print(items3[-5:-7:-1]) # [55, 68] print(items3[::-2]) # [100, 45, 55, 99, 35] # 列表的比較運(yùn)算 items5 = [1, 2, 3, 4] items6 = list(range(1, 5)) # 兩個(gè)列表比較相等性比的是對(duì)應(yīng)索引位置上的元素是否相等 print(items5 == items6) # True items7 = [3, 2, 1] # 兩個(gè)列表比較大小比的是對(duì)應(yīng)索引位置上的元素的大小 print(items5 <= items7) # True
值得一提的是,由于列表是可變類型,所以通過索引操作既可以獲取列表中的元素,也可以更新列表中的元素。對(duì)列表做索引操作一樣要注意索引越界的問題,對(duì)于有N個(gè)元素的列表,正向索引的范圍是0到N-1,負(fù)向索引的范圍是-1到-N,如果超出這個(gè)范圍,將引發(fā)IndexError異常,錯(cuò)誤信息為:list index out of range。
2.2列表元素的遍歷
如果想逐個(gè)取出列表中的元素,可以使用for循環(huán)的,有以下兩種做法。
方法一
items = ['Python', 'Java', 'Go', 'Kotlin'] for index in range(len(items)): print(items[index])
方法二
items = ['Python', 'Java', 'Go', 'Kotlin'] for item in items: print(item)
講到這里,我們可以用列表的知識(shí)來重構(gòu)上面“擲色子統(tǒng)計(jì)每個(gè)點(diǎn)數(shù)出現(xiàn)次數(shù)”的代碼。
import random counters = [0] * 6 for _ in range(6000): face = random.randint(1, 6) counters[face - 1] += 1 for face in range(1, 7): print(f'{face}點(diǎn)出現(xiàn)了{(lán)counters[face - 1]}次')
上面的代碼中,我們用counters列表中的六個(gè)元素分別表示1到6的點(diǎn)數(shù)出現(xiàn)的次數(shù),最開始的時(shí)候六個(gè)元素的值都是0。接下來用隨機(jī)數(shù)模擬擲色子,如果搖出1點(diǎn)counters[0]的值加1,如果搖出2點(diǎn)counters[1]的值加1,以此類推。大家感受一下,這段代碼是不是比之前的代碼要簡單優(yōu)雅很多。
3.列表的方法
和字符串一樣,列表類型的方法也很多,下面為大家講解比較重要的方法。
3.1添加和刪除元素
items = ['Python', 'Java', 'Go', 'Kotlin'] # 使用append方法在列表尾部添加元素 items.append('Swift') print(items) # ['Python', 'Java', 'Go', 'Kotlin', 'Swift'] # 使用insert方法在列表指定索引位置插入元素 items.insert(2, 'SQL') print(items) # ['Python', 'Java', 'SQL', 'Go', 'Kotlin', 'Swift'] # 刪除指定的元素 items.remove('Java') print(items) # ['Python', 'SQL', 'Go', 'Kotlin', 'Swift'] # 刪除指定索引位置的元素 items.pop(0) items.pop(len(items) - 1) print(items) # ['SQL', 'Go', 'Kotlin'] # 清空列表中的元素 items.clear() print(items) # []
需要提醒大家,在使用remove方法刪除元素時(shí),如果要?jiǎng)h除的元素并不在列表中,會(huì)引發(fā)ValueError異常,錯(cuò)誤消息是:list.remove(x): x not in list。在使用pop方法刪除元素時(shí),如果索引的值超出了范圍,會(huì)引發(fā)IndexError異常,錯(cuò)誤消息是:pop index out of range。
從列表中刪除元素其實(shí)還有一種方式,就是使用Python中的del關(guān)鍵字后面跟要?jiǎng)h除的元素,這種做法跟使用pop方法指定索引刪除元素沒有實(shí)質(zhì)性的區(qū)別,但后者會(huì)返回刪除的元素,前者在性能上略優(yōu)(del對(duì)應(yīng)字節(jié)碼指令是DELETE_SUBSCR,而pop對(duì)應(yīng)的字節(jié)碼指令是CALL_METHOD和POP_TOP,不理解就跳過,不用管它!?。。?。
items = ['Python', 'Java', 'Go', 'Kotlin'] del items[1] print(items) # ['Python', 'Go', 'Kotlin']
3.2元素位置和次數(shù)
列表類型的index方法可以查找某個(gè)元素在列表中的索引位置;因?yàn)榱斜碇性试S有重復(fù)的元素,所以列表類型提供了count方法來統(tǒng)計(jì)一個(gè)元素在列表中出現(xiàn)的次數(shù)。請(qǐng)看下面的代碼。
items = ['Python', 'Java', 'Java', 'Go', 'Kotlin', 'Python'] # 查找元素的索引位置 print(items.index('Python')) # 0 print(items.index('Python', 2)) # 5 # 注意:雖然列表中有'Java',但是從索引為3這個(gè)位置開始后面是沒有'Java'的 print(items.index('Java', 3)) # ValueError: 'Java' is not in list
再來看看下面這段代碼。
items = ['Python', 'Java', 'Java', 'Go', 'Kotlin', 'Python'] # 查找元素出現(xiàn)的次數(shù) print(items.count('Python')) # 2 print(items.count('Go')) # 1 print(items.count('Swfit')) # 0
3.3元素排序和反轉(zhuǎn)
列表的sort操作可以實(shí)現(xiàn)列表元素的排序,而reverse操作可以實(shí)現(xiàn)元素的反轉(zhuǎn),代碼如下所示。
items = ['Python', 'Java', 'Go', 'Kotlin', 'Python'] # 排序 items.sort() print(items) # ['Go', 'Java', 'Kotlin', 'Python', 'Python'] # 反轉(zhuǎn) items.reverse() print(items) # ['Python', 'Python', 'Kotlin', 'Java', 'Go']
4.列表的生成式
在Python中,列表還可以通過一種特殊的字面量語法來創(chuàng)建,這種語法叫做生成式。我們給出兩段代碼,大家可以做一個(gè)對(duì)比,看看哪一種方式更加簡單優(yōu)雅。
通過for循環(huán)為空列表添加元素。
# 創(chuàng)建一個(gè)由1到9的數(shù)字構(gòu)成的列表 items1 = [] for x in range(1, 10): items1.append(x) print(items1) # 創(chuàng)建一個(gè)由'hello world'中除空格和元音字母外的字符構(gòu)成的列表 items2 = [] for x in 'hello world': if x not in ' aeiou': items2.append(x) print(items2) # 創(chuàng)建一個(gè)由個(gè)兩個(gè)字符串中字符的笛卡爾積構(gòu)成的列表 items3 = [] for x in 'ABC': for y in '12': items3.append(x + y) print(items3)
通過生成式創(chuàng)建列表。
# 創(chuàng)建一個(gè)由1到9的數(shù)字構(gòu)成的列表 items1 = [x for x in range(1, 10)] print(items1) # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 創(chuàng)建一個(gè)由'hello world'中除空格和元音字母外的字符構(gòu)成的列表 items2 = [x for x in 'hello world' if x not in ' aeiou'] print(items2) # ['h', 'l', 'l', 'w', 'r', 'l', 'd'] # 創(chuàng)建一個(gè)由個(gè)兩個(gè)字符串中字符的笛卡爾積構(gòu)成的列表 items3 = [x + y for x in 'ABC' for y in '12'] print(items3) # ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
下面這種方式不僅代碼簡單優(yōu)雅,而且性能也優(yōu)于上面使用for循環(huán)和append方法向空列表中追加元素的方式。可以簡單跟大家交待下為什么生成式擁有更好的性能,那是因?yàn)镻ython解釋器的字節(jié)碼指令中有專門針對(duì)生成式的指令(LIST_APPEND指令);而for循環(huán)是通過方法調(diào)用(LOAD_METHOD和CALL_METHOD指令)的方式為列表添加元素,方法調(diào)用本身就是一個(gè)相對(duì)耗時(shí)的操作。對(duì)這一點(diǎn)不理解也沒有關(guān)系,記住“強(qiáng)烈建議用生成式語法來創(chuàng)建列表”這個(gè)結(jié)論就可以了。
5.嵌套的列表
Python語言沒有限定列表中的元素必須是相同的數(shù)據(jù)類型,也就是說一個(gè)列表中的元素可以任意的數(shù)據(jù)類型,當(dāng)然也包括列表。如果列表中的元素又是列表,那么我們可以稱之為嵌套的列表。嵌套的列表可以用來表示表格或數(shù)學(xué)上的矩陣,例如:我們想保存5個(gè)學(xué)生3門課程的成績,可以定義一個(gè)保存5個(gè)元素的列表保存5個(gè)學(xué)生的信息,而每個(gè)列表元素又是3個(gè)元素構(gòu)成的列表,分別代表3門課程的成績。但是,一定要注意下面的代碼是有問題的。
scores = [[0] * 3] * 5 print(scores) # [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
看上去我們好像創(chuàng)建了一個(gè)5 * 3的嵌套列表,但實(shí)際上當(dāng)我們錄入第一個(gè)學(xué)生的第一門成績后,你就會(huì)發(fā)現(xiàn)問題來了,我們看看下面代碼的輸出。
# 嵌套的列表需要多次索引操作才能獲取元素 scores[0][0] = 95 print(scores) # [[95, 0, 0], [95, 0, 0], [95, 0, 0], [95, 0, 0], [95, 0, 0]]
我們不去過多的解釋為什么會(huì)出現(xiàn)這樣的問題,如果想深入研究這個(gè)問題,可以通過Python Tutor網(wǎng)站的可視化代碼執(zhí)行功能,看看創(chuàng)建列表時(shí)計(jì)算機(jī)內(nèi)存中發(fā)生了怎樣的變化,下面的圖就是在這個(gè)網(wǎng)站上生成的。建議大家不去糾結(jié)這個(gè)問題,現(xiàn)階段只需要記住不能用[[0] * 3] * 5]這種方式來創(chuàng)建嵌套列表就行了。那么創(chuàng)建嵌套列表的正確做法是什么呢,下面的代碼會(huì)給你答案。
scores = [[0] * 3 for _ in range(5)] scores[0][0] = 95 print(scores) # [[95, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
總結(jié)
Python中的列表底層是一個(gè)可以動(dòng)態(tài)擴(kuò)容的數(shù)組,列表元素在內(nèi)存中也是連續(xù)存儲(chǔ)的,所以可以實(shí)現(xiàn)隨機(jī)訪問(通過一個(gè)有效的索引獲取到對(duì)應(yīng)的元素且操作時(shí)間與列表元素個(gè)數(shù)無關(guān))。我們暫時(shí)不去觸碰這些底層存儲(chǔ)細(xì)節(jié)以及列表每個(gè)方法的漸近時(shí)間復(fù)雜度(執(zhí)行這個(gè)方法耗費(fèi)的時(shí)間跟列表元素個(gè)數(shù)的關(guān)系),等需要的時(shí)候再告訴大家。現(xiàn)階段,大家只需要知道列表是容器,可以保存各種類型的數(shù)據(jù),可以通過索引操作列表元素,知道這些就足夠了。
以上就是Python常用數(shù)據(jù)類型之列表使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Python列表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python數(shù)據(jù)分析之使用matplotlib繪制折線圖、柱狀圖和柱線混合圖
matplotlib是python的一個(gè)模塊,用于繪制各種圖形,今天介紹一下折線圖的繪制,下面這篇文章主要給大家介紹了關(guān)于Python數(shù)據(jù)分析之使用matplotlib繪制折線圖、柱狀圖和柱線混合圖的相關(guān)資料,需要的朋友可以參考下2022-05-05python使用epoll實(shí)現(xiàn)服務(wù)端的方法
今天小編就為大家分享一篇python使用epoll實(shí)現(xiàn)服務(wù)端的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10python開發(fā)實(shí)例之Python的Twisted框架中Deferred對(duì)象的詳細(xì)用法與實(shí)例
這篇文章主要介紹了python開發(fā)實(shí)例之Python的Twisted框架中Deferred對(duì)象的詳細(xì)用法與實(shí)例,需要的朋友可以參考下2020-03-03MacBook m1芯片采用miniforge安裝python3.9的方法示例
這篇文章主要介紹了MacBook m1芯片采用miniforge安裝python3.9的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04python smtplib模塊自動(dòng)收發(fā)郵件功能(二)
這篇文章主要為大家詳細(xì)介紹了python smtplib模塊自動(dòng)收發(fā)郵件功能的第二篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05備戰(zhàn)618!用Python腳本幫你實(shí)現(xiàn)淘寶秒殺
本次的文章,分享一個(gè)淘寶秒殺腳本,這個(gè)腳本用Python編寫,使用了Python庫selenium,并且通過selenium + chromedriver,用程序控制chrome瀏覽器,完成搶購的一系列操作.有了這個(gè)腳本,大家至少可以與其他的機(jī)器人站在同一起跑線上,公平搶購喜歡的寶貝 ,需要的朋友可以參考下2021-06-06