給妹子講python-S01E01python容器的使用技巧之列表

醬油哥在掘金發表於2019-02-17

歡迎關注公眾號:python資料科學家

【要點搶先看】

1.python中的容器資料型別概述
2.列表型別的異構性、有序性和本地可變性三大優勢
3.列表的基本操作(增、刪、改、分片索引)
4.列表的分片賦值與本地排序

【妹子說】今天開始學python啦,不過我們從哪裡開始學起呢?

Python中有一種被稱之為“容器”的資料型別,專門用來存放其他型別的物件,就好比小時候用的文具盒,裡面放著鉛筆、尺子、橡皮等等。很多人剛剛使用Python的時候,往往最先接觸的就是這種容器物件,比如列表、字典、元組等等。它們功能全面,使用也很方便,可以解決很多實際問題。

那麼,第一季我們就首先從這些好用、實用的python容器入手吧,第一個就介紹列表:

Python列表用起來非常靈活,它有三大優點,我們一個一個來說,聊完了這三個優點,基本上列表的基本操作我們就掌握了:

第一個優點:

列表裡想裝啥就裝啥,即:他可以包含不同種類、任意型別的物件,甚至可以巢狀列表,專業點的詞兒叫:異構性;

我們看一個例子:

L1 = [12345]
L2 = [1`spam`, [2.34]]
L3 = []
複製程式碼

看這三個列表的初始化過程,異構性就搞清楚了,特別是L2列表,它同時包含了好幾種不同的資料型別,甚至還巢狀了列表。

第二個優點:

列表裡裝的元素都是有順序的,可以按照位置序號獲取單個元素,也可以用分片的方法來進行多個連續元素的獲取,來個專業詞彙,叫做:有序性。

按位置序號索引,例如L1[2]這種方式來訪問列表中的元素只是最簡單的一種,我來重點來說說分片操作這個獨特用法,先看看這個例子:

L = [1,2,3,4,5,6,7,8]
print(L[1:3])

[2, 3]
複製程式碼

我們從列表L中從左往右擷取了一個片段。關於擷取片段左右邊界與索引值的對應關係,我們只需記住這麼一個口訣“左閉右開”就OK了:

分片索引中第一個引數1表示左側開始的索引1(從0開始計數),因此起始的元素就是整形數2,第二個引數3表示在右側終止的索引值為3,即整形數4,但要記住他是不包含在擷取的序列中的。

分片還有幾種常見用法:

如果省略掉終止索引,就表示一直擷取到末尾:

L = [1,2,3,4,5,6,7,8]
print(L[1:])

[2, 3, 4, 5, 6, 7, 8]
複製程式碼

同理,如果省略掉起始索引,就表示從起始元素就開始擷取:

L = [1,2,3,4,5,6,7,8]
print(L[:4])

[1, 2, 3, 4]
複製程式碼

還可以用負索引,目前我們使用的都是正索引,即從左往右的索引值,最左側的索引值為0,往右依次加1;還有一種負索引的表示法,即從右往左數,最右側是-1,往左依次減1,即-2,-3以此類推:

L = [1,2,3,4,5,6,7,8]
print(L[3:-1])

[4, 5, 6, 7]
複製程式碼

【妹子問】:那我想跳著擷取呢?

那就用上第三個引數,步進值引數,這個預設是1,即1個挨著1個的取,如果我們想跳著擷取,那就得專門設定這個步進引數了。

L = [1,2,3,4,5,6,7,8]
print(L[0::2])

[1, 3, 5, 7]
複製程式碼

這時候【妹子問了一個很有內涵的問題】:我對擷取出的分片進行修改,會影響到原始的列表嗎?

那我們還是眼見為實:

L = [1,2,3,4,5,6,7,8]
b = L[3:-1]
print(`before change:b={}`.format(b))
b[0]=111
print(`after change:b={}`.format(b))
print(`after change:L={}`.format(L))

before change:b=[4567]
after change:b=[111567]
after change:L=[12345678]
複製程式碼

很明顯,對原始列表L進行分片切割後,產生了一個全新的列表。用變數b獲取了L的分片後,實質是獲取了L分片的一個新的獨立拷貝。因此,你在列表b上做修改,是影響不了L的。

第三個優點:

列表的大小和內容可以隨意改變,在插入、刪除、修改列表元素時,不需要建立一份新的列表拷貝,而是在原來的記憶體地址上直接修改列表物件。這個叫“本地可修改”

首先看增加新元素的三個使用場景:

L = [1,2,3,4]
L.append(5)
print(L)

[1, 2, 3, 4, 5]

L = [1,2,3,4]
L.insert(1,10)
print(L)

[1, 10, 2, 3, 4]

L = [1,2,3,4]
L.extend([11,22,33])
print(L)

[1, 2, 3, 4, 11, 22, 33]
複製程式碼

這三個用法有些不同,append方法只能在尾部加入;insert方法可在任意位置加入,比如上面例子,我們在列表的索引位置為1的地方加入元素10,如果指定的索引值大於序列的總長度,則自動加到末尾;extend方法則可以在尾部一次性加入多個元素

這時,【妹子自己操作了一把】:

L = [1,2,3,4,5]
L = L.insert(6,2)
print(L[2])

Traceback (most recent call last):
 File "E:/12homework/12homework.py", line 3in <module>
print(L[2])
TypeError: `NoneType` object is not subscriptable
複製程式碼

然後,就沒有然後了。。。這裡犯了一個常見的錯誤,因為我們說過插入是就地修改,而不是返回修改後的新列表。Insert方法的返回值是None,這麼幹換句話說,會徹底失去之前列表的引用,因為你把None值賦給了L,你就無法找到之前的列表了。append和extend方法也是這樣。

刪除,依據使用需求也有這幾種使用場景:

最簡單直接的,用remove方法,傳入指定要刪除的物件,注意:它也是在原列表上就地刪除,返回值為None

L1 = [`aa`,`bb`,`cc`]
L1.remove(`aa`)
print(L1)

[`bb``cc`]
複製程式碼

這裡注意,還有一個內建方法del,它額外的功能是可以刪除列表中的一個分片

del L1[1:3]
複製程式碼

還有一個pop方法,它在末端刪除一個元素,並可以將刪除的元素作為返回值返回給呼叫者

L1 = [1,2,3]
print(L1.pop())#末端刪除一個元素,彈出刪除的值
print(L1)

3
[1, 2]
複製程式碼

【妹子問】那麼元素修改,除了像下面這種直接用索引做元素修改的情況外,還有什麼有趣的用法?

L = [4,5,6,7,8,9]
L[0] = 0
複製程式碼

那必須要來點有意思的,主要就說分片賦值本地排序這兩個問題:

L = [4,5,6,7,8,9]
L[1:3] = [`aa`,`bb`,`cc`,`dd`]
print(L)

[4, `aa``bb``cc``dd`, 7, 8, 9]
複製程式碼

分片賦值的本質是先在原列表上刪除指定分片,然後在刪除的位置插入新的列表,因此左右兩邊的長度可以不等。

本地排序非常方便,看看下面的例子就明白了。注意排序也是在本地修改,而不是將排好序的列表作為返回值返回。

L = [1,5,3,8,3,2,10]
L.sort()
print(L)
L.reverse()
print(L)

[12335810]
[10853321]
複製程式碼

【妹子說】果然呀,所謂三大優點講完了,列表的基本用法算是弄明白了,那下次再講講字典和元組吧。

歡迎關注公眾號:python資料科學家

公眾號二維碼:

給妹子講python-S01E01python容器的使用技巧之列表

相關文章