python中的切片操作應該怎麼理解?

a = [1, 3 ,5 ,6, 8]

如果按序列的理解方法,執行a[3:4] =[4] 這個操作尚可以理解為把a中第3個元5替換為4

但是如果執行的 a[3:3]=[4],卻是插入操作,得到 a = [1, 3, 5, 4, 6, 8]

按序列方法,[3:3]位置的選取讓人難以理解

那麼怎麼理解比較容易記憶呢?


首先說明, a[3:3]=4,這種操作應該是會報錯的,原因後面會說道的,其次我們來簡單說一說 list 切片,list 切片會返回一個新的list,但是這個list是原來的list的淺拷貝產生出來的。

所以你對切片結果的操作會影響到最初的list,也就是說 a[3:4] = 4 這個操作會替換原來的值,

為什麼說a[3:3]=4,這個操作不正確,因為a[3:3] 即使是空的,也是返回一個 [], 是可迭代的,

官方文檔中也提到:

slice of s from i to j is replaced by the contents of the iterable t

但是很遺憾的是 4 是 int 類型,並不是 iterable,所以這個操作會有錯,如果想賦值的話,可以使用 a[3:3]=(4.)完成插入操作,至於這個時候為什麼是插入操作呢?其實理解起來也比較簡單,a[3:3]返回的結果是 [],也就是對原來的list切片,這個片段不存在任何值,現在你添加上了,所以會自動追加到 3 索引的後面


剛好今天看了一篇關於python切片的公眾號文章,把切片的特性說的很清楚了,也更新了我對切片的認識。

Python切片高級特性完全解讀

題主提到的a[3:3]=4這種形式並不會報錯,而是作為佔位符,進行list拼接操作,這種操作可以在任意位置進行拼接,也可以理解為插入操作。這裡直接用文章里的例子了,比list.append這種更方便。也推薦大家記切片的完整模式[i : n : m]。

li = [1, 2, 3, 4]

# 在頭部拼接

li[:0] = [0] # [0, 1, 2, 3, 4]

# 在末尾拼接

li[len(li):] = [5,7] # [0, 1, 2, 3, 4, 5, 7]

# 在中部拼接

li[6:6] = [6] # [0, 1, 2, 3, 4, 5, 6, 7]


大家講了很多,這裡我只補充一點,切片的特點:顧首不顧尾


a = [1, 3 ,5 ,6, 8]
print(a[3:3])

結果:

[]

a[3:3]返回的結果是 [],,這個片段不存在任何值

現在給它賦值一個可迭代對象a[3:3] = [4] (如果a[3:3] = 4,會報錯,4是int 不是可迭代對象)

a = [1, 3, 5, 6, 8]
a[3:3] = [4]
print(a)

結果

[1, 3, 5, 4, 6, 8]

因為a[3:3]返回的結果是 [],這個片段不存在任何值,現在a[3:3]=[4],其實就是[]在a列表中的位置索引為3處添加一個值,因此得到a = [1, 3, 5, 4, 6, 8]

列表切片是採用「左閉右開」的原則(從起始索引到結束索引,不包括結束索引所對應的元素)

而a[3:4]這個位置是有元素的『5』所以可以替換成『4』

一般這種模式下:

sequence[starting_index : ending_index]

可以得到從起始索引到結束索引(不包括結束索引所對應的元素)之間的元素,起始索引和結束索引都是可選的,如果沒有提供或者用None作為索引值,切片操作會從序列的最開始處開始,或者直到序列的最末尾結束。其中,開始和結束的索引值可以超出字元串長度。starting_index應該小於ending_index,否則返回空字元串。

另外切片是截取生成list的操作,最好不要拿來賦值,如果把某個元素替換成別的元素,可以直接賦值給對應的索引位置

把元素插入到指定的位置,比如索引號為1的位置:

可以用

a = [1, 3, 5, 6, 8]
a.insert(1,python)
print(a)

結果

[1, python, 3, 5, 6, 8]

要把某個元素替換成別的元素,可以直接賦值給對應的索引位置:

a = [1, 3, 5, 6, 8]
a[1] = python
print(a)

結果

[1, python, 5, 6, 8]


a[3:3]有個默認的參數1,寫全了就是a[3:3:1],也就是說python會從列表a的索引3處元素開始切片,結束位置是索引3所在位置的元素,但是不取結束位置的元素,結果返回的就是[],所以a[3:3]=[4],其實就是[] = [4]賦值操作,而[]在a列表中的位置為列表第四位(索引3處),因此得到a = [1, 3, 5, 4, 6, 8]。題主注意題目描述中的小問題「執行a[3:4] =[4] 這個操作尚可以理解為把a中第3個元5替換為4」應該是:「執行a[3:4] =[4] 這個操作尚可以理解為把a中第4個元素6替換為4」。


弄個環境執行一下。


可以看到,python的切片實際上是有兩種語義,準確可以說是有三種語義:d&>0時的插入,d&<0時的刪除,還有一種是d=0,就是替換了。

那麼這個d是什麼呢?在第七行d = n - norig,; d大於0小於0還是等於0就是看這個n和norig哪個大,從而進行不同的語義操作,這裡的n是列表v的長度(也就量賦值號右邊的列表:[4]的長度),norig = ihigh-ilow就是想要切片的大小,a[3:4]的話,norig=4-3=1; 那麼就是看想要切片的大小與要右邊列表的大小哪個大,哪個小。

如果想要切片的大小 剛好等於 右邊列表的大小 那麼就直接執行最後的for循環,實現替換;

如果想要切片的大小 小於 右邊列表的大小(a[3:3]=[4]),那麼就執行插入操作,你要切片的大小放不下賦值號右邊的列表,就會執行插入(比如a[3:4] = [5, 6]也會執行插入操作)

還有就是刪除,就不多說了,題主問的就是上面兩種情況。

以上對代碼進行了簡化,如果題主想了解具體過程,可以去看一下源碼。

參考源碼:

Python 2.5.1


切片是截取(生成)list的操作,不要拿來賦值


輸出字元串中任意位置


要很簡單的記憶這個問題,你可能需要從列表的數據存儲格式出發,引用指向。


推薦閱讀:

TAG:Python | Python3x | Python入門 |