在我們實(shí)際開(kāi)發(fā)中,經(jīng)常需要將一組數(shù)據(jù)存儲(chǔ)起來(lái),以便使用。如果學(xué)習(xí)了其他的語(yǔ)言可能知道數(shù)組(Array)這個(gè)數(shù)據(jù)結(jié)構(gòu),它就可以將多個(gè)數(shù)據(jù)進(jìn)行存儲(chǔ),訪問(wèn)數(shù)據(jù)可以通過(guò)數(shù)組下標(biāo)的方式,的進(jìn)行獲取。如果你是python開(kāi)發(fā)者,那么可以使用更加靈活的列表(list)和元組(tuple),來(lái)進(jìn)行數(shù)據(jù)儲(chǔ)存。下面我們先簡(jiǎn)單了解下列表和元組的基本使用。
列表是動(dòng)態(tài)的,長(zhǎng)度可以改變,可以隨意增加,修改或刪除元素。
初始化列表
a = list() b = [] # 可以通過(guò)range快速創(chuàng)建list c = list(range(1,6)) print("a:", a) print("b:", b) print("c:", c) # a: [] # b: [] # c: [1, 2, 3, 4, 5]
添加元素
append:在列表的末尾添加一個(gè)元素
>>l = [] >>l.append("python") >>l ['python']
extend:使用可迭代對(duì)象中的所有元素來(lái)擴(kuò)展列表
>>l = ["python"] >>t = ["java"] >>l.extend(t) >>l ['python', 'java']
insert:在給定的位置插入一個(gè)元素。第一個(gè)參數(shù)是要插入的元素的索引,所以 list_name.insert(0, x) 插入列表頭部
>>l = ["python", "java"] >>l.insert(1,"go") >>l ['python', 'go', 'java']
刪除元素
remove(x):從列表中刪除值為x的第一項(xiàng)。 如果沒(méi)有需要?jiǎng)h除的值,那就拋出異常
>>l = ["python", "java"] >>l.remove("java") >>l ['python'] >>l.remove("test") Traceback (most recent call last): File "input>", line 1, in module> ValueError: list.remove(x): x not in list
pop: 刪除列表中給定位置的元素并返回它。如果沒(méi)有給定位置,pop() 將會(huì)刪除并返回列表中的最后一個(gè)元素
>>l = ["python", "java", "go"] >>l.pop() 'go' >>l ['python', 'java'] >>l.pop(1) 'java' >>l.pop(1) Traceback (most recent call last): File "input>", line 1, in module> IndexError: pop index out of range
del: Python 中的關(guān)鍵字,專門用來(lái)執(zhí)行刪除操作,它不僅可以刪除整個(gè)列表,還可以刪除列表中的某些元素
>>l = ["python", "java", "go", "js"] >>del l[0:1] >>l ['java', 'go', 'js'] >>del l[0] >>l ['go', 'js']
clear(): 移除列表中的所有元素。等價(jià)于 del a[:]
>>l = ["python", "java", "go", "js"] >>l.clear() >>l []
ps: 這里注意和del 的區(qū)別, clear是清空, del list_name 是刪除,內(nèi)存也釋放
修改元素
修改單個(gè)可以通過(guò)下標(biāo)的方法
>>l = ["python", "go", "java"] >>l[0] = "PYTHON" >>l ['PYTHON', 'go', 'java']
修改一組數(shù)據(jù)可以通過(guò)切片的方式
>>l = ["python", "go", "java"] >>l[0:2] = "PYTHON", "GO" >>l ['PYTHON', 'GO', 'java'] >>l[0:2] = ["python", "go"] >>l ['python', 'go', 'java']
查詢?cè)?/strong>
index(x) :方法用來(lái)查找某個(gè)元素在列表中出現(xiàn)的位置(也就是索引),如果該元素不存在,則會(huì)導(dǎo)致 ValueError 錯(cuò)誤
>>l ['python', 'go', 'java'] >>l.index("python") 0 >>l.index("python1") Traceback (most recent call last): File "input>", line 1, in module> ValueError: 'python1' is not in list
count() :用來(lái)統(tǒng)計(jì)某個(gè)元素在列表中出現(xiàn)的次數(shù)
>>l ['python', 'go', 'java'] >>l.count("PYTHON") 0 >>l.count("python") 1
其他操作
sort:對(duì)列表中的元素進(jìn)行排序
>>l ['go', 'java', 'python'] >>l.sort(reverse=True) >>l ['python', 'java', 'go'] >>l.sort() >>l ['go', 'java', 'python']
reverse: 反轉(zhuǎn)元素
>>l = [1,2,3,4,5] >>l.reverse() >>l [5, 4, 3, 2, 1]
copy: 返回列表的一個(gè)淺拷貝,等價(jià)于 a[:]
>>l [5, 4, 3, 2, 1] >>a = l.copy() >>a [5, 4, 3, 2, 1]
1-使用列表實(shí)現(xiàn)棧
棧(stack)特點(diǎn)就是后進(jìn)先出, 使用列表實(shí)現(xiàn)是非常容易的,要添加一個(gè)元素到堆棧的頂端,使用 append() 。要從堆棧頂部取出一個(gè)元素,使用 pop() ,不用指定索引。
stack = [] stack.append(1) stack.append(2) stack.append(3) stack.append(4) stack.pop() # 4 stack.pop() # 3 stack.pop() # 2 stack.pop() # 1 # 注意捕捉錯(cuò)誤
2-實(shí)現(xiàn)隊(duì)列
from collections import deque queue = deque(["python", "go", "java"]) queue.append("python") queue.append("go") print(queue) queue.popleft() queue.popleft() print(queue)
返回結(jié)果
deque(['python', 'go', 'java', 'python', 'go'])
deque(['java', 'python', 'go'])
列表推導(dǎo)式
a = [x ** 2 for x in range(10)] b = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y] # 嵌套列表推導(dǎo)式 matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], ] c = [[row[i] for row in matrix] for i in range(4)] print("a:", a) print("b:", b) print("c:", c)
返回
a: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
b: [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
c: [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
元組是靜態(tài),大小固定,不可以對(duì)元素進(jìn)行增加,修改或刪除的操作
創(chuàng)建元組
a = 1, 2, 3 print("a", a) b = (1, 2, 3) print("b", b) # 將字符串轉(zhuǎn)換成元組 tup1 = tuple("hello") print("將字符串轉(zhuǎn)換成元組", tup1) # 將列表轉(zhuǎn)換成元組 list1 = ['Python', 'Java', 'C++', 'JavaScript'] tup2 = tuple(list1) print("將列表轉(zhuǎn)換成元組", tup2) # 將字典轉(zhuǎn)換成元組 dict1 = {'a': 100, 'b': 42, 'c': 9} tup3 = tuple(dict1) print("將字典轉(zhuǎn)換成元組", tup3) # 將區(qū)間轉(zhuǎn)換成元組 range1 = range(1, 6) tup4 = tuple(range1) print("將區(qū)間轉(zhuǎn)換成元組", tup4)
返回結(jié)果
a (1, 2, 3)
b (1, 2, 3)
將字符串轉(zhuǎn)換成元組 ('h', 'e', 'l', 'l', 'o')
將列表轉(zhuǎn)換成元組 ('Python', 'Java', 'C++', 'JavaScript')
將字典轉(zhuǎn)換成元組 ('a', 'b', 'c')
將區(qū)間轉(zhuǎn)換成元組 (1, 2, 3, 4, 5)
訪問(wèn)元素
a = (1, 2, 3, 4, 5) # 通過(guò)下標(biāo) print(a[0]) # 通過(guò)切片:a[start : end : step] print(a[0:4:2])
返回結(jié)果
1
(1, 3)
刪除
a = (1, 2, 3, 4, 5) del a
元組是靜態(tài),列表是動(dòng)態(tài)
元組修改
l = (1,2,3,4) id(l) # 4497372488 l = l + (5,6) id(l) # 4494985832
列表修改
l = [1,2,3,4] id(l) # 4499169160 l = l + [5,6] id(l) # 4495787016
通過(guò)上面可以發(fā)現(xiàn)元組是不可以改變的,這里強(qiáng)調(diào)一點(diǎn)很多新手對(duì)這個(gè) l = l + (5,6) 很不難理解,不是說(shuō)元組不可以修改的嗎,那為什么這里可以修改?記住這里雖然可以執(zhí)行,但是他是創(chuàng)建了一個(gè)新的元組,這時(shí)候的 l 不是原來(lái)的 l, 可以通過(guò) id 查詢(或則執(zhí)行 l[0] = -1 就會(huì)報(bào)錯(cuò))
在這里我多說(shuō)幾句,這里的靜態(tài)和動(dòng)態(tài),大白話來(lái)講是列表是可以進(jìn)行列表的操作(新增,刪除,修改),一般操作行為下他的內(nèi)存地址不變(通過(guò)id查看),這和他的實(shí)現(xiàn)有關(guān),但是元組就會(huì)改變,所以新的元組和原來(lái)的不一樣,一般時(shí)候有人(面試官或則開(kāi)發(fā)不小心)會(huì)問(wèn)你 a = ([1,2], 3,4), 為什么可以進(jìn)行a[0].append(3),但是id(a)前后不變,這就是0下標(biāo)的元素是列表,列表可以修改的。
列表需要更多內(nèi)存,元組需要更少內(nèi)存
list_t = [] print("列表初始化時(shí)候大小:", list_t.__sizeof__()) tuple_t = () print("元組初始化時(shí)候大小:", tuple_t.__sizeof__())
返回結(jié)果
列表初始化時(shí)候大小: 40
元組初始化時(shí)候大小: 24
看到結(jié)果有沒(méi)有發(fā)現(xiàn)列表比元組大18字節(jié),那么問(wèn)題來(lái)了:這18字節(jié)是怎么來(lái)的?這是由于列表是動(dòng)態(tài)的,它需要存儲(chǔ)指針來(lái)指向?qū)?yīng)的元素(占用 8 個(gè)字節(jié))。另外,由于列表中元素可變,所以需要額外存儲(chǔ)已經(jīng)分配的長(zhǎng)度大?。ㄕ加?8 個(gè)字節(jié)),這樣才能實(shí)時(shí)追蹤列表空間的使用情況。但是對(duì)于元組,情況就不同了,元組長(zhǎng)度大小固定,且存儲(chǔ)元素不可變,所以存儲(chǔ)空間也是固定的。
列表不可被hash,元組可以被hash
tuple_t = (1, 2) print("元組hash值:", hash(tuple_t)) list_t = [1, 2] print("列表hash值:", hash(list_t))
執(zhí)行結(jié)果
Traceback (most recent call last):
File "/Users/linjian/MonitorCenter/MonitorCenter/apps/t6.py", line 4, in module>
print("列表hash值:", hash(list_t))
TypeError: unhashable type: 'list'
元組hash值: 3713081631934410656
從上面的結(jié)果可以發(fā)現(xiàn)元組是可以被hash,但列表卻是不可以。如果基礎(chǔ)扎實(shí)的應(yīng)該會(huì)反應(yīng)過(guò)來(lái),python中hash需要滿足是不可變類型的數(shù)據(jù)結(jié)構(gòu)(字符串str、元組tuple、對(duì)象集objects)
執(zhí)行效率
# 初始化一個(gè)相同元素的列表和元組使用情況 (djangoDemo) MonitorCenter % python -m timeit 'x=(1,2,3,4,5,6)' 100000000 loops, best of 3: 0.0103 usec per loop (djangoDemo) MonitorCenter % python -m timeit 'x=[1,2,3,4,5,6]' 10000000 loops, best of 3: 0.0514 usec per loop # 元組和列表索引操作對(duì)比 (djangoDemo) MonitorCenter % python -m timeit 'x=(1,2,3,4,5,6)' 'y=x[3]' 10000000 loops, best of 3: 0.0267 usec per loop (djangoDemo) MonitorCenter % python -m timeit 'x=(1,2,3,4,5,6)' 'y=x[3]' 10000000 loops, best of 3: 0.0265 usec per loop
上面的運(yùn)行結(jié)果顯示: 元組初始化遠(yuǎn)快于列表 ,大概有五倍的差距,但是索引操作的時(shí)候速度沒(méi)有多大差距
截止目前為止,我們可以簡(jiǎn)單總結(jié)列表和元組的區(qū)別有如下:
再說(shuō)使用場(chǎng)景前先講一下,在python后臺(tái),對(duì)靜態(tài)數(shù)據(jù)做一些資源緩存,通常因?yàn)槔厥諜C(jī)制的存在,一些變量不使用,python就會(huì)回收他們所占的內(nèi)存,但是對(duì)于一些靜態(tài)變量(比如說(shuō)元組),當(dāng)他們占用不大時(shí)候(長(zhǎng)度1~20的元組),python會(huì)暫時(shí)緩存這部分內(nèi)存,這樣下次就可以不再向操作系統(tǒng)發(fā)出請(qǐng)求,分配內(nèi)存資源,而是直接使用用緩存中之前的內(nèi)存空間,這樣大大加快了程序的運(yùn)行速度。所以一般有時(shí)候數(shù)據(jù)量不大,我經(jīng)常使用元組替代列表。到目前為止我們可以簡(jiǎn)單的總結(jié)出場(chǎng)景可以如下所示:
創(chuàng)建空的列表,是使用list()效率好還是[]?
(djangoDemo) MonitorCenter % python -m timeit 'x=list()'
10000000 loops, best of 3: 0.087 usec per loop
(djangoDemo) MonitorCenter % python -m timeit 'x=[]'
100000000 loops, best of 3: 0.0177 usec per loop
通過(guò)上面的測(cè)試可以知道是[]快。list()函數(shù)調(diào)用,python中函數(shù)調(diào)用會(huì)創(chuàng)建stack并且會(huì)進(jìn)行參數(shù)檢查,[]是一個(gè)內(nèi)置C函數(shù),可以直接調(diào)用,因此效率更高。
執(zhí)行相乘操作時(shí)候,是 *= 效率好, 還是*?
(djangoDemo) MonitorCenter % python -m timeit 'x = [1,2,3]' 'x*=3'
10000000 loops, best of 3: 0.0903 usec per loop
(djangoDemo) MonitorCenter % python -m timeit 'x = [1,2,3]' 'x = x * 3'
10000000 loops, best of 3: 0.104 usec per loop
從結(jié)果可以看出是*效率會(huì)低點(diǎn)。*= 中會(huì)預(yù)分配,不足的時(shí)候擴(kuò)容,但是* 會(huì)按照每次的量進(jìn)行分配大小
為什么輸出是這樣的?
list_1 = [1, 2, 3, 4] list_2 = [1, 2, 3, 4] list_3 = [1, 2, 3, 4] list_4 = [1, 2, 3, 4] for idx, item in enumerate(list_1): del item for idx, item in enumerate(list_2): list_2.remove(item) for idx, item in enumerate(list_3[:]): list_3.remove(item) for idx, item in enumerate(list_4): list_4.pop(idx) print("list_1", list_1) print("list_2", list_2) print("list_3", list_3) print("list_4", list_4)
結(jié)果
list_1 [1, 2, 3, 4]
list_2 [2, 4]
list_3 []
list_4 [2, 4]
list_2為什么輸出是[2,4]? 因?yàn)樵诘谝淮蝿h除后,list_2變成了 [2,3,4], 然后在刪除輪循到到第二個(gè)數(shù)據(jù)也就是3(大部分都以為是2,但是2從原來(lái)的下表2變?yōu)?),可以參看下面的
give next element: 0 0 ---> 1 1 2 2 3 3 4 give next element: 1 0 2 1 ---> 3 2 4 give next element: 2 0 2 1 4
list_3 為什么是[], 還記得之前我們說(shuō)copy時(shí)候,copy等于[:](淺拷貝),所以輪詢的和刪除的不是同一內(nèi)存的數(shù)據(jù)。
list_4可以結(jié)合list_2思考,因?yàn)榈谝淮蝿h除,第二次刪除是下標(biāo)2,但是數(shù)據(jù)變了,下標(biāo)2的數(shù)據(jù)不是原來(lái)的2,而是3.
官方文檔
淺析Python中的列表和元組
到此這篇關(guān)于python中列表(list)和元組(tuple)的文章就介紹到這了,更多相關(guān)python列表(list)和元組(tuple)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
標(biāo)簽:興安盟 綿陽(yáng) 拉薩 廊坊 渭南 內(nèi)江 亳州 黔東
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《python中列表(list)和元組(tuple)的深入講解》,本文關(guān)鍵詞 python,中,列表,list,和,元組,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。