Python序列類型切片取值徹底剖析

簡(jiǎn)介

Python中對(duì)序列類型某個(gè)子集或者區(qū)間的檢索稱作切片。實(shí)際上,切片功能非常強(qiáng)大,能夠提供對(duì)可編輯序列類型數(shù)據(jù)的增、刪、改、查等各種操作,運(yùn)用恰當(dāng)?shù)脑挄?huì)極大地節(jié)省編碼量。因此,切片知識(shí)在Python開發(fā)中極其重要,如果啃不掉這根硬骨頭,將會(huì)給你未來的Python開發(fā)之路帶來極大挫敗感。
全國(guó)二級(jí)Python考試中考查的序列類型主要有三種,即字符串、元組和列表,也是實(shí)戰(zhàn)中使用最頻繁的數(shù)據(jù)結(jié)構(gòu)。其中,列表是可編輯的,而字符串和元組僅提供讀操作。本文將以列表為例,詳細(xì)介紹各種Python考級(jí)及實(shí)戰(zhàn)中需要的切片取值技巧及有關(guān)注意事項(xiàng)。

創(chuàng)新互聯(lián),專注為中小企業(yè)提供官網(wǎng)建設(shè)、營(yíng)銷型網(wǎng)站制作、響應(yīng)式網(wǎng)站開發(fā)、展示型成都網(wǎng)站建設(shè)、成都網(wǎng)站制作等服務(wù),幫助中小企業(yè)通過網(wǎng)站體現(xiàn)價(jià)值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營(yíng)銷推廣問題。

1. 基礎(chǔ)引例

我們假設(shè)讀者是經(jīng)過初步的切片學(xué)習(xí)在遇到技巧及概念障礙時(shí)才閱讀此文的。為此,可以通過一個(gè)基本類型例子,引出切片涉及的基本概念,進(jìn)而有助于更形象地理解切片。本部分中,如果尚存在疑問,請(qǐng)暫時(shí)保留,待認(rèn)真閱讀完全文后,應(yīng)該能得到圓滿解答。
直接創(chuàng)建列表 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
切片的目的是把上述列表中符合某個(gè)規(guī)律(如等差數(shù)列、等比數(shù)列或者更復(fù)雜的規(guī)律)的元素組成的子集取出來。例如:
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a[1:5:2]
[1, 3]
【簡(jiǎn)析】上述切片中,1為切片的起始索引,5為切片的結(jié)束索引,2為切片的步長(zhǎng)。步長(zhǎng)為2決定了切片的方向是從左向右。從索引1(包括)開始向索引5沿著從左向右順序切(根據(jù)步長(zhǎng)為2的規(guī)律)出符合條件的下標(biāo)元素,僅有兩個(gè),即:a[1],a[3]。那么,a[5]是不是包含在結(jié)果中呢?不是。因?yàn)樵诖_定符合條件的切片子集時(shí),還有一個(gè)限定條件是:左閉右開。即對(duì)于上面的索引,應(yīng)當(dāng)是:[1,5)。請(qǐng)參考下圖:
Python序列類型切片取值徹底剖析
上面的引例中出現(xiàn)如下概念及問題:
【概念】步長(zhǎng)(符號(hào)與大?。?、切片的起始索引位置、切片的終止索引位置、切片的方向。
【問題】
? 如何確定參與切片的子集?
? 從哪個(gè)索引開始沿著什么方向以多大的跨度(步長(zhǎng))切片?切片的結(jié)束索引是什么?
? 當(dāng)切片的起始索引位置與終止索引位置為空時(shí)如何處理?

2. 切片語法格式

Sequence[start: end: step]

現(xiàn)總結(jié)切片規(guī)則如下:

  1. step:切片的跨度,也就是切片跳躍的長(zhǎng)度,也稱“步長(zhǎng)”,默認(rèn)值(省略時(shí))為1。要求:必須是除零外的整數(shù)(可正可負(fù))
  2. step為正時(shí),則從左向右切片,如果start(可為0)和end同符號(hào)且start > end,則切片結(jié)果集一定為空
  3. step為負(fù)時(shí),則從右向左切片,如果start(可為0)和end同符號(hào)且start < end,則切片結(jié)果集一定為空
  4. start:代表切片的起始索引位置。為空時(shí),表示切片起始索引位置是整個(gè)列表的最開始(而且,結(jié)果集中包括該元素)。注意:這里的“最開始”并不等于“最左邊”。
    4.1當(dāng)step為正,start對(duì)應(yīng)列表的最左邊(包含)。
    4.2當(dāng)step為負(fù),start對(duì)應(yīng)列表的最右邊(=len(列表))。
  5. end:代表切片的截至索引位置。為空時(shí),表示切片終止索引位置是整個(gè)列表的最后一個(gè)(切片到該元素結(jié)束,至于結(jié)果集中是否包括該元素,取決于step)。注意:這里的“最后一個(gè)”并不等于“最右邊”。
    5.1當(dāng)step為正,end對(duì)應(yīng)列表的最右邊(=len(列表))。
    5.2當(dāng)step為負(fù),end對(duì)應(yīng)列表的最左邊(包含)。
  6. start和end同時(shí)為空的時(shí)候,表示序列中所有元素都要參與切片。當(dāng)step絕對(duì)值為1時(shí),切片結(jié)果中包含序列中所有元素;當(dāng)step絕對(duì)值大于1時(shí),切片結(jié)果將按step值對(duì)應(yīng)的切片規(guī)律包含序列中相應(yīng)元素。
  7. 切片的時(shí)候,不存在索引越界的問題。例如,給定切片索引小于切片最小索引值,則截止到列表最左邊;如果給定切片索引大于切片最大索引值,則截止到列表最右邊。

【注意】步長(zhǎng)值為0導(dǎo)致錯(cuò)誤提示“ValueError: slice step cannot be zero”。

3. 正索引和負(fù)索引與等價(jià)項(xiàng)

實(shí)質(zhì)上,序列類型提供了兩種索引類型:正索引和負(fù)索引。還是以上面提到的列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]為例,請(qǐng)各位觀察下圖。
Python序列類型切片取值徹底剖析
從圖中看出:

Python序列類型切片取值徹底剖析
顯然,存在這樣的絕對(duì)值關(guān)系:
|0|+|-10|=10,|1|+|-9|=10,……|9|+|-1|=10

重要技巧

從上面看到,每一個(gè)列表(各種序列類型)中的元素都有兩種下標(biāo)(注意:a[0]對(duì)應(yīng)a[-10])。在切片分析中,可以把下標(biāo)轉(zhuǎn)換成對(duì)應(yīng)的下標(biāo)來分析。如:
a[-6::2]等價(jià)于a[4::2]
a[:-6:-1] 等價(jià)于a[:4:-1]
a[-5:-2:2] 等價(jià)于a[5:8:2]

a[:2] 等價(jià)于a[0:2] 等價(jià)于a[0:2:1]
a[2:] 等價(jià)于a[2:10] 等價(jià)于a[2:10:1]
a[:2:] 等價(jià)于a[0:2] 等價(jià)于 a[0:2:1]
★a[::-1]等價(jià)于a[-1:-11:-1]

4. 典型切片取值舉例

下面所有例子還是基于前面的列表:

a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
為方便總結(jié),我們來分小類型舉例切片的應(yīng)用。

4.1. 切片表達(dá)式中僅有一對(duì)冒號(hào)情形

【提示】這種情況下,暗含著一個(gè)前提是:步長(zhǎng)值step取值為1,因此切片方向遵循“自左向右”切的原則。
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

4.1.1 最簡(jiǎn)單情形

a[2:6]
[2, 3, 4, 5]
a[2:9]
[2, 3, 4, 5, 6, 7, 8]
【提示】在此兩例中,符合“左閉右開”原則,故最后切片結(jié)果集中去掉最后一個(gè)下標(biāo)元素。

4.1.2 切片截止索引位置“超界”

根據(jù)上面切片規(guī)則7的說明,切片操作時(shí)索引不存在真正“越界”問題。請(qǐng)結(jié)合切片規(guī)則7看下面的舉例。
a[2:10]
[2, 3, 4, 5, 6, 7, 8, 9]
【解析】根據(jù)“左閉右開”原則,切片結(jié)果集將包含a[2],a[3]……直到a[9]的8個(gè)元素。
a[2:20]
[2, 3, 4, 5, 6, 7, 8, 9]
【解析】根據(jù)切片規(guī)則7,a[2:20]等價(jià)于a[2:10](10=len(a),即列表最右邊)。下面兩個(gè)例子理由同這兩個(gè)例子:
a[-3:10]
[7, 8, 9]
a[-3:20]
[7, 8, 9]

4.1.3 切片的起始索引位置超界

a[-10:-8]
[0, 1]
a[-100:-8]
[0, 1]
a[-100:2]
[0, 1]
a[-10:2]
[0, 1]
【解析】根據(jù)切片規(guī)則7,a[-100:-8]等價(jià)于a[-10:-8],a[-10:2] 等價(jià)于a[-100:2]。另一方面,a[-10:-8] 等價(jià)于a[0:-8](等價(jià)于a[0:2]),a[-10:2] 等價(jià)于a[0:2],故有上面運(yùn)行結(jié)果。

4.1.4 切片起始索引或截止索引為負(fù)

a[-2:6]
[]
【解析】a[-2:6]等價(jià)于a[8:6],也等價(jià)于a[-2:6:1]和a[8:6:1],此時(shí)step=1(省略),易知切片結(jié)果集為空。
a[6:-2]
[6, 7]
【解析】a[6:-2]等價(jià)于a[6:8],也等價(jià)于a[6:-2:1]和a[6:8:1],此時(shí)step=1(省略),結(jié)合“左閉右開”原則,易知結(jié)果集對(duì)應(yīng)[a[6],a[7]](而不包含a[8]),即切片結(jié)果集為[6, 7]。

4.1.5 切片規(guī)則2應(yīng)用

a[6:2]
[]
a[-2:-6]
[]
【解析】符合切片規(guī)則2,易知切片結(jié)果集為空。
a[-6:-2]
[4, 5, 6, 7]
【解析】a[-6:-2] 等價(jià)于a[4:8],結(jié)合“左閉右開”原則,易知結(jié)果集對(duì)應(yīng)[a[4],a[5],a[6],a[7]](而不包含a[8]),即切片結(jié)果集為[4,5,6, 7]。

4.1.6 省略切片起始索引時(shí)

a[:4]
[0, 1, 2, 3]
a[:-4]
[0, 1, 2, 3, 4, 5]
【解析】根據(jù)上面切片規(guī)則4.1,a[:4]等價(jià)于a[0:4],a[:-4] 等價(jià)于a[0:-4],而a[0:-4]又等價(jià)于a[0:6] ,結(jié)合“左閉右開”原則,易知有上面的切片結(jié)果集。

4.1.7 省略切片截止索引時(shí)

a[4:]
[4, 5, 6, 7, 8, 9]
a[-4:]
[6, 7, 8, 9]
【解析】根據(jù)上面切片規(guī)則5.1,a[4:]等價(jià)于a[4:10] (10=len(a)),a[-4:]等價(jià)于a[6:],而a[6:]等價(jià)于a[6:10] (10=len(a)),結(jié)合切片規(guī)則6“左閉右閉”原則(a[9]包含在結(jié)果集中),易知有上面的切片結(jié)果集。

4.1.8 切片起始索引和截止索引均省略時(shí)

a[:]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
【解析】根據(jù)上面切片規(guī)則4.1和5.1,a[:]等價(jià)于a[0:10](10=len(a)),而根據(jù)“左閉右開”原則,結(jié)果集中應(yīng)當(dāng)包含a[0],a[1],……a[9],故有上述切片結(jié)果集。

4.2. 切片表達(dá)式中有兩對(duì)冒號(hào)情形

在切片表達(dá)式有兩對(duì)冒號(hào)情況下,當(dāng)step為1時(shí)(因?yàn)檫@種情況下可以省略第二對(duì)冒號(hào),所以對(duì)應(yīng)上面僅有一對(duì)冒號(hào)時(shí)),絕大部分情形我們已經(jīng)討論過。
【前提】本部分中,我們還是使用與上面同樣結(jié)構(gòu)與內(nèi)容的列表a,如下所示:
a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

4.2.1 step>1時(shí)

不失一般性,以下討論不妨假設(shè)step=2。先看下面的例子。
a[2:7:2]
[2, 4, 6]
a[:3:2]
[0, 2]
a[:-3:2]
[0, 2, 4, 6]
a[3::2]
[3, 5, 7, 9]
a[-3::2]
[7, 9]
【解析】首先注意到,step=2決定了切片方向是自左向右。當(dāng)step>1時(shí),切片起始索引值默認(rèn)為0。對(duì)于負(fù)數(shù)形式的起始還是截止索引值都可以轉(zhuǎn)換成等價(jià)的正數(shù)形式索引值(例如a[:-3:2]等價(jià)于a[:7:2]),a[-3::2] 等價(jià)于a[7::2])來分析的。再結(jié)合“左閉右開”原則,這一組例題應(yīng)該不難理解,故細(xì)節(jié)的解釋在此省略。

4.2.2 step為負(fù)整數(shù)時(shí)

例1

a[8:3:-1]
[8, 7, 6, 5, 4]
【解析】首先注意到,step為-1決定了切片方向是自右向左。本例中,切片起始索引為8,終止索引為3,再結(jié)合切片“左閉右開”原則,故切片結(jié)果集中元素有[a[8],a[7],a[6],a[5],a[4]],即[8,7,6,5,4]。

例2

a[10:0:-2]
[9, 7, 5, 3, 1]
【解析】首先注意到,step為-2決定了切片方向是自右向左。其次,根據(jù)上面切片原則7,切片的時(shí)候不存在索引越界情況,a[10]不存在,則繼續(xù)往內(nèi)分析,a[9]=9。于是,結(jié)合切片“左閉右開”原則和步長(zhǎng)(即跨度)為2,故切片結(jié)果集中元素有[a[9],a[7],a[5],a[3],a[1]],即[9,7,5,3,1]。

例3

a[0:10:-2]
[]
【解析】首先注意到,step為-2決定了切片方向是自右向左。而切片初始索引為0,即列表的左邊界,此時(shí)再向左切肯定沒有元素可切了。因此,根據(jù)切片規(guī)則3,結(jié)果為空列表。

例4

a[:4:-1]
[9, 8, 7, 6, 5]
【解析】首先注意到,step為-1決定了切片方向是自右向左。此時(shí),切片初始索引對(duì)應(yīng)列表的最右邊(=len(列表)),即有切片從索引10(實(shí)際從索引9開始,包含該索引)開始沿著自右向左的方向切片,直到索引4(不包含,依據(jù)是“左閉右開”),故有上述切片結(jié)果。

例5

a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【解析】首先注意到,step為-1決定了切片方向是自右向左。那么,接下來最關(guān)鍵的問題是搞清:在step為負(fù)數(shù)且切片初始索引和切片終止索引沒有提供的情況下,這個(gè)切片初始索引和切片終止索引的值為多少。結(jié)合上面規(guī)則4.2和5.2,初始索引對(duì)應(yīng)列表的最右邊(=len(列表)),切片的截至索引位置為列表的最左邊的左側(cè)(即參與切片的子集中包含索引為0的元素)。當(dāng)然,也可以簡(jiǎn)單根據(jù)上面規(guī)則6確定出最終的切片結(jié)果為列表中原來所有元素的倒序。

例6

a[5::-2]
[5, 3, 1]
【解析】首先注意到,step為-2決定了切片方向是自右向左。切片初始索引為5,結(jié)果集中自然包含a[5]。根據(jù)上面分析,本例中切片的截至索引位置為列表的最左邊的左側(cè)(即參與切片的子集中包含索引為0的元素)。從等價(jià)關(guān)系來分析的話,a[5::-2]等價(jià)于a[5:-11:-2](下標(biāo)-11對(duì)應(yīng)著下標(biāo)-10再往左,類似于下標(biāo)9再往右對(duì)應(yīng)的下標(biāo)10)。所以,有此例中運(yùn)行結(jié)果。

思考題

? a[0::-1]的結(jié)果是多少?
? a[:-3:2] 的結(jié)果是多少?
? a[1:6:-1] 的結(jié)果是多少?
? a[-6::-1] 的結(jié)果是多少?
? 連續(xù)切片操作:a[:8][2:5][-1:] 的結(jié)果是多少?
? a[2+1:3*2:7%3] 的結(jié)果是多少?
? 下列代碼片斷的運(yùn)行結(jié)果是什么?
for i in range(1,100)[2::3][-10:]:
print(i)
【提示】利用range函數(shù)生成1-99的整數(shù),然后取3的倍數(shù),再取最后十個(gè)。

小結(jié)

理論上而言,只要條件表達(dá)式得當(dāng),可以通過單次或多次切片操作實(shí)現(xiàn)任意切取目標(biāo)值。初看上去,切片操作的基本語法比較簡(jiǎn)單,但是深挖起來,并不簡(jiǎn)單。因此,如果不徹底搞清楚內(nèi)在邏輯,也極容易產(chǎn)生錯(cuò)誤,而且這種錯(cuò)誤有時(shí)隱蔽得比較深,難以察覺。
作為補(bǔ)充,本文中提到的“左閉右開”原則,更細(xì)致地說法是“開始閉結(jié)束開”原則。即是說,開始索引對(duì)應(yīng)元素參與切片運(yùn)算,而結(jié)束索引對(duì)應(yīng)元素并不參與切片運(yùn)算。另外,步長(zhǎng)值為負(fù)數(shù),并且在省略切片起始索引或者切片終止索引情況下,這兩種索引的默認(rèn)值應(yīng)當(dāng)結(jié)合“切片不存在索引越界”原則進(jìn)行正確理解。本文通過詳細(xì)例子總結(jié)歸納了切片操作的各種情況。若有錯(cuò)誤和不足之處請(qǐng)各位指正!

文章名稱:Python序列類型切片取值徹底剖析
文章網(wǎng)址:http://muchs.cn/article4/ghsoie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司、網(wǎng)站制作搜索引擎優(yōu)化、關(guān)鍵詞優(yōu)化、網(wǎng)站改版、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)