有關 python 切片的趣事

2023-06-10 12:00:20

哈嘍大家好,我是鹹魚

今天來講一個我在實現 python 列表切片時遇到的趣事

在正式開始之前,我們先來了解一下切片(slice)

切片操作是存取序列(列表、字串......)中元素的另一種方法,它可以存取一定範圍內的元素,通過切片操作,可以生成一個新的序列

語法如下

name[start : end : step]
  • start 是切片的起始索引值,當 start 是序列首位時可以省略
  • end 是切片結束索引值,當 end 是序列末位時可以省略
  • step 為步長,可以不提供,預設是1,不能為0,為負數時表示列表翻轉

需要注意的是,切片操作遵循包頭不包尾的原則,即從序列的第 start 位索引起,向右取到後 end-1 位元素為止,按 m 間隔過濾

下面舉一些關於切片的例子

# 獲取列表的前 n 個元素:
lst = [1, 2, 3, 4, 5, 6]
n = 3
result = lst[:n]
print(result)  # [1, 2, 3]

# 獲取列表的後 n 個元素:
lst = [1, 2, 3, 4, 5, 6]
n = 3
result = lst[-n:]
print(result)  # [4, 5, 6]

# 獲取列表中的偶數元素:
lst = [1, 2, 3, 4, 5, 6]
result = lst[1::2]
print(result)  # [2, 4, 6]

# 獲取列表中的奇數元素:
lst = [1, 2, 3, 4, 5, 6]
result = lst[::2]
print(result)  # [1, 3, 5]

# 獲取列表中的倒數第二個元素:
lst = [1, 2, 3, 4, 5, 6]
result = lst[-2:-1]
print(result)  # [5]

# 獲取列表中的最後兩個元素:
lst = [1, 2, 3, 4, 5, 6]
result = lst[-2:]
print(result)  # [5, 6]

根據 GPT 的回答,Fortran 是最早支援切片語法的語言,歷史上曾經有多種語言支援切片操作

上面這些語言雖然說都支援切片語法,但我覺得不夠 python 那樣的靈活簡潔

  1. 簡潔而直觀的語法:

Python 的切片語法非常簡潔和直觀,使用起來非常方便。通過使用冒號(:)來指定起始位置、結束位置和步長,可以輕鬆地進行切片操作。

  1. 強大的切片功能:

Python 的切片語法不僅支援基本的切片操作,還可以使用負數索引和省略號(...)來處理更復雜的情況。這使得對列表、字串、元組等序列型別的資料進行靈活的切片成為可能

再介紹完了切片之後,我們來進入正題,那天鹹魚在寫一個關於列表切片操作的檔案

現象

我們知道:根據單個索引進行取值時,如果索引越界,就會報錯

list1 = [1,2,3]
print(list1[5])

"""
報錯資訊如下:
Traceback (most recent call last):
  File "E:\PycharmProjects\projects\demo\草稿紙.py", line 2, in <module>
    print(list1[5])
IndexError: list index out of range
"""

但是當鹹魚不小心將切片結束索引值設定成了超過了列表長度的值的時候,發現居然沒有報錯

list1 = [1,2,3]
print(list1[1:5]) # 結果[2, 3]

是不是很有趣,Python 中的切片操作不會引發索引越界的錯誤

關於這個現象,官方檔案裡面是有介紹的

The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j. If i or j is greater than len(s), use len(s).

If i is omitted or None, use 0. If j is omitted or None, use len(s). If i is greater than or equal to j, the slice is empty.

也就是說,對於序列 s :

  • 當初始索引值或者結束索引值大於序列長度時,就用長度值(len(s))作為索引值
  • 當初始索引值沒寫或者是 None 時,用 0 作為初始索引值
  • 當結束索引值沒寫或者是 None 時,用序列長度值(len(s))作為初始索引值
  • 當初始索引值大於等於結束索引值時,結果為空物件
my_list = [1, 2, 3, 4, 5]

# 有效的切片範圍
print(my_list[1:4])  # 輸出: [2, 3, 4]

# 超出索引範圍的切片,會自動調整為有效的索引
print(my_list[1:10])  # 輸出: [2, 3, 4, 5]

# 負數索引也適用
print(my_list[-3:10])  # 輸出: [3, 4, 5]

總結

Python 的切片語法設計得很安全,即使指定的切片索引超出了序列的長度,也不會引發索引越界錯誤。相反,它會自動調整切片範圍,只返回有效的結果

當進行切片操作時,Python會根據切片的引數和可用的索引範圍來確定切片的實際範圍

雖然不知道龜哥為什麼設計 Python 的切片語法要允許索引超出邊界,而不是設計成丟擲索引錯誤?

但是可以知道的是,這種設計使得切片操作更加靈活和方便,無需手動檢查索引範圍或引發索引越界異常

它允許我們在切片操作中不必擔心邊界情況,並且可以更加簡潔地處理列表、字串和其他序列型別的操作