Python從菜鳥到高手:分片(Slicing)

mug發表於2021-09-09

  分片操作是從序列A中獲取一個子序列B。序列A可以稱為父序列。從A中獲取B,需要指定B在A中的開始索引和結束索引,因此,分片操作需要指定兩個索引。

  由於字串可以看做是字元的序列,所以我們可以用序列的這個分片特性擷取子字串。

  本例透過分片操作獲取一個Url的一級域名和完整的域名。

url = ''
print(url[8:15])				#  執行結果:geekori
print(url[8:19])				#  執行結果:geekori.com

程式執行結果如下圖所示。

圖片描述

  在上面的程式碼中,使用url[8:15]來擷取url中的“geekori”,其中8和15是url中的兩個索引。我們可以看到,兩個索引之間要使用冒號(:)分隔。可能有的讀者會發現,索引15並不是“i”的索引,而是“.”的索引,沒錯,在指定子序列結束索引時,要指定子序列最後一個元素的下一個元素的索引,因此,應該指定“.”的索引,而不是“i”的索引。

  那麼如果子序列的最後一個元素恰好是父序列的最後一個元素該怎麼辦呢?例如,url中的最後一個元素是“m”,如果要擷取“”,子序列的結束索引應該如何指定呢?其實子序列的結束索引只要指定父序列最後一個元素的索引加1即可。由於父索引最後一個元素“m”的索引是18,因此,要擷取“”,需要指定結束索引為19,也就是url[8:19]。

  1. 省略子序列的索引

首先看一個用分片擷取數字序列的例子。

本例透過分片操作擷取numbers序列中的某個子序列。

numbers = [1,2,3,4,5,6,7,8]
print(numbers[3:5])				#  執行結果:[4, 5]
print(numbers[0:1])				#  執行結果:[1]
print(numbers[5:8])				#  執行結果:[6, 7, 8]
print(numbers[-3:-1])				#  執行結果:[6,7]

程式執行結果如下圖所示。

圖片描述

  本例透過將結束索引設為0,獲取一個空序列。

numbers = [1,2,3,4,5,6,7,8]
print(numbers[-3:0])					#  執行結果:[]

程式執行結果如下圖所示。

圖片描述

  Python語言規定,如果結束索引比開始索引晚出現,那麼就會返回空序列,在這裡索引0比索引-3晚出現。如果要使用負數作為索引,並且獲取的子序列的最後一個元素與父序列的最後一個元素相同,那麼可以省略結束索引,或結束索引用正整數。

本例使用負數作為開始索引,並省略結束索引。

numbers = [1,2,3,4,5,6,7,8]
print(numbers[-3:]) 					# 省略了結束索引,執行結果:[6, 7, 8]
print(numbers[-3:8])					# 結束索引用了正整數作為索引,執行結果:[6, 7, 8]

程式執行結果如下圖所示。

圖片描述

  這種省略索引的方式統一適用於開始索引。
本例省略了開始索引。

numbers = [1,2,3,4,5,6,7,8]
print(numbers[:3])					# 擷取父序列中前3個元素作為子序列,執行結果:[1, 2, 3]

程式執行結果如下圖所示。

圖片描述

  如果開始索引和結束索引都不指定,那麼會複製整個子序列。
  本例下面的程式碼透過省略開始索引和結束索引,複製了整個序列。

numbers = [1,2,3,4,5,6,7,8]
print(numbers[:])					# 複製整個序列,執行結果:[1, 2, 3, 4, 5, 6, 7, 8]

程式執行結果如下圖所示。

圖片描述

  在對序列分片時,預設的步長是1,也就是說,獲取的子序列的元素都是相鄰的。如果要獲取不相鄰的元素,就需要指定步長。例如,要獲取索引為1、3、5的元素作為子序列的元素,就需要將步長設為2。

  本例透過改變分片操作的步長,獲取元素不相鄰的子序列。

numbers = [1,2,3,4,5,6,7,8,9]
print(numbers[1:6:2])		# 指定步長為2,執行結果:[2, 4, 6]

程式執行結果如下圖所示。

圖片描述

  在上面的程式碼中,使用numbers[1:6:2]獲取了索引為1、3、5的元素作為子序列的元素,其中2是步長,我們可以看到,開始索引、結束索引和步長之間都用冒號分隔(:)。

  其實,開始索引,結束索引和步長都是可以省略的。

本例在分片時指定步長,但省略了開始索引以及結束索引。

numbers = [1,2,3,4,5,6,7,8,9]
print(numbers[:7:2])   	# 省略了開始索引,執行結果:[1, 3, 5, 7]
print(numbers[::2])	# 省略了開始索引和結束索引,執行結果:[1, 3, 5, 7, 9]
print(numbers[3::2])	# 省略了結束索引,執行結果:[4, 6, 8]

程式執行結果如下圖所示。

圖片描述

  步長不能為0,但可以是負數。如果步長為0,會丟擲異常,如果步長是負數,分片會從序列的右側開始,這時開始索引要大於結束索引。

  在使用分片步長時,分別使用了負數和0。

numbers = [1,2,3,4,5,6,7,8,9]
# 步長為-2,從索引為8的元素開始,一直到索引為3的元素,執行結果:[9, 7, 5]
print(numbers[8:2:-2])	
print(numbers[8:2:-1])	   # 步長為-1,執行結果:[9, 8, 7, 6, 5, 4]
print(numbers[1:6:0])	   # 步長為0,會丟擲異常

程式執行結果如下圖所示。

圖片描述

  在上面的程式碼中,如果步長為負數,那麼分片的開始索引需要大於結束索引。例如,numbers[8:2:-2]表示從索引為8的元素開始,往前掃描,直到索引為2的元素的上一個元素,也就是索引為3的元素為止。
當然,如果使用負數作為步長,還有一些比較燒腦的用法,得出這些用法的分片結果,需要動一下腦筋。

  本例將負數作為分片步長。

numbers = [1,2,3,4,5,6,7,8,9]
#  步長為-3,從序列最後一個元素開始,一直到序列第一個元素結束,執行結果:[9, 6, 3]
print(numbers[::-3])		
#  步長為-2,從序列的最後一個元素開始,一直到索引為4的元素結束,執行結果:[9, 7, 5]
print(numbers[:3:-2])

程式執行結果如下圖所示。

圖片描述

  本例要求從Python控制檯輸入一個Url和一個數字n。然後對Url分片,獲取Url的Scheme和Host,最後根據這個數字生成一個包含1到n的序列,然後對該序列進行兩次分片,一次獲取序列中的所有奇數,一次獲取序列中的所有偶數,並分兩行錯位顯示。

url = input("請輸入一個Https網址:")
scheme = url[0:5]					#  分片獲取Url中的Scheme
host = url[8:]						#  分片獲取Url中的Host

print("scheme:", scheme)
print("host:",host) 

str = input("請輸入一個整數:")
n = int(str);

numbers = range(1,n)				# 產生包含1到n的數值型別的序列
numbers1 = numbers[0::2]			# 分片獲取序列中的奇數
numbers2 = numbers[1::2]			# 分片獲取序列中的偶數
for number in numbers1:				# 在第1行輸出所有的奇數
    print(number, end= " ")
print("")
print(" ",end="")
for number in numbers2:				# 在第2行錯位輸出所有的偶數
    print(number, end= " ")

程式執行結果如下圖所示。

圖片描述

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/506/viewspace-2814264/,如需轉載,請註明出處,否則將追究法律責任。

相關文章