Skip to content

切片和 range 的記法

range() 和切片其實很像。

range(start, stop, step)

a[start:stop:step]

都可以先記成:

start   # 從哪裡開始,包含
stop    # 到哪裡停止,不包含
step    # 每次走幾格,也決定方向

其中最重要的是:

方向只看 step,不要看 start、stop 有沒有負號。


1. 先分清楚兩種負號

切片裡面的負號有兩種完全不同的意思。

負索引:代表位置

a[-3]

意思是倒數第 3 個元素。

假設:

a = [0, 1, 2, 3, 4, 5, 6]

可以這樣看:

元素       0   1   2   3   4   5   6

正索引     0   1   2   3   4   5   6
負索引    -7  -6  -5  -4  -3  -2  -1

所以:

-1 → 6
-2 → 5
-3 → 4
-4 → 3
-5 → 2
-6 → 1
-7 → 0

負索引只是表示「從尾巴數的位置」,不代表往左走。


負的 step:才代表反方向

例如:

a[5:1:-1]

第三個參數:

step = -1

所以方向是:

←

會依序使用:

5, 4, 3, 2

因此:

a[5:1:-1]

得到:

[5, 4, 3, 2]

2. 方向只看第三個參數

可以直接這樣記:

step > 0   → 往右
step < 0   → 往左

如果沒有寫 step:

a[2:5]

其實可以想成:

a[2:5:1]

所以是:

→

即使寫成:

a[-5:-2]

裡面有兩個負號,方向還是:

→

因為第三個參數沒有寫:

step = 1

所以:

start、stop 的負號只管位置。

step 的正負才管方向。


3. 三步驟記法

以後看到:

a[start:stop:step]

如果覺得很亂,就固定做三件事:

① 先看 step,決定方向

② start、stop 如果是負索引,就先轉成正索引

③ 把它當成 range(start, stop, step) 去跑

第一步:看 step

step > 0  → →
step < 0  → ←

如果沒有寫:

step = 1

第二步:負索引轉成正索引

公式:

正索引 = len(a) + 負索引

例如:

a = [0, 1, 2, 3, 4, 5, 6]

所以:

len(a) = 7

如果看到:

-4

就想:

7 + (-4)
= 3

所以:

-4 → 3

第三步:當成 range

例如:

a[2:6:2]

可以想成:

range(2, 6, 2)

會產生:

2, 4

所以拿:

a[2]
a[4]

4. 範例:a[:-4]

假設:

a = [0, 1, 2, 3, 4, 5, 6]

看到:

a[:-4]

① 看方向

沒有第三個參數,所以:

step = 1
方向 →

② 負索引轉正

len(a) = 7

-4 → 7 - 4
   → 3

所以腦中可以把:

a[:-4]

轉成:

a[:3]

③ 當成 range

因為是從最前面開始,所以想成:

range(0, 3, 1)

得到:

0, 1, 2

所以:

a[:-4]

結果:

[0, 1, 2]

5. 範例:a[-5:-6]

還是:

a = [0, 1, 2, 3, 4, 5, 6]

看到:

a[-5:-6]

不要因為看到:

-5 → -6

就覺得它會往左走。

① 看方向

沒有第三個參數:

step = 1
方向 →

② 負索引轉正

-5 → 2
-6 → 1

所以:

a[-5:-6]

可以想成:

a[2:1]

③ 當成 range

range(2, 1, 1)

但是現在:

從 2 開始

方向 →

終點卻是 1

方向不對,所以什麼都拿不到。

結果:

[]

可以直接記:

range(2, 1, 1)
→ []

a[2:1:1]
→ []

6. 如果真的要從 -5 走到 -6

要自己把方向改成往左:

a[-5:-6:-1]

① 看方向

step = -1
方向 ←

② 負索引轉正

-5 → 2
-6 → 1

所以變成:

a[2:1:-1]

③ 當成 range

range(2, 1, -1)

得到:

2

所以:

a[-5:-6:-1]

結果:

[2]

7. 再看一個比較複雜的

a[-2:-6:-1]

假設:

a = [0, 1, 2, 3, 4, 5, 6]

① 看方向

step = -1
方向 ←

② 負索引轉正

-2 → 5
-6 → 1

所以:

a[-2:-6:-1]

可以想成:

a[5:1:-1]

③ 當成 range

range(5, 1, -1)

得到:

5, 4, 3, 2

所以:

a[-2:-6:-1]

得到:

[5, 4, 3, 2]

8. slice 和 range 很像

例如:

range(2, 6, 1)

產生:

2, 3, 4, 5

而:

a[2:6:1]

使用的 index 也是:

2, 3, 4, 5

兩個都遵守:

start 包含
stop 不包含
step 決定方向與間隔

所以算切片時,把它想成 range() 很方便。


9. 但是 range 裡面的負數不能這樣轉

這一點要特別注意。

切片:

a[-4:]

這裡的:

-4

是 index(索引)。

所以可以利用:

len(a) + (-4)

轉成正索引。

但是:

range(-4, 3)

這裡的 -4 只是普通的數字 -4。

所以:

list(range(-4, 3))

結果是:

[-4, -3, -2, -1, 0, 1, 2]

不會因為某個 list 的長度而轉成正數。

所以要分清楚:

切片中的負 start / stop
→ 負索引
→ 可以利用 len(a) 轉成正索引


range() 裡面的負數
→ 普通的負數
→ 不要轉

10. [::-1] 是一個要特別注意的情況

例如:

a[::-1]

第三個參數:

step = -1

所以先知道:

方向 ←

因為 start 和 stop 都沒有寫,而且現在是反向走,所以 Python 會從最右邊開始,一直走過最左邊。

例如:

a = [0, 1, 2, 3, 4, 5, 6]
a[::-1]

得到:

[6, 5, 4, 3, 2, 1, 0]

可以先直接記成:

[::-1] → 整個反轉

要注意:

a[::-1]

不能直接寫成:

a[-1:-1:-1]

因為切片中「沒有寫 stop」和「stop 寫成 -1」不是同一件事。

目前先把:

[::-1]

當成常用特殊寫法記住即可。


11. 最簡單心法

看到:

a[x:y:z]

就固定想:

① 看 z 決定方向

   z > 0  → →
   z < 0  → ←


② x、y 如果是負索引

   正索引 = len(a) + 負索引


③ 當成 range(x, y, z)

   start 要
   stop 不要

也就是:

先看第三格定方向
前兩格只管位置
負位置用 len() 轉正
最後照 range() 跑

最重要的是:

負索引不代表反向。

只有負的 step 才代表反向。