Python 列表切片详解

庖丁解牛,「以无厚入有间」。Python 的列表切片大抵也是这个意思——用最薄的语法,在数据的骨节之间游刃。三个参数,两个冒号,不声不响地把一整条列表分割成你需要的任何形状。

列表切片(List Slicing)是 Python 中访问列表子序列的核心语法。通过切片可以高效地提取、复制或操作列表的任意部分,无需编写循环。语法简洁到近乎沉默,却是日常编程中最频繁的手势之一。

核心概念

基本语法

1
list[start:stop:step]
参数说明默认值
start起始索引(包含)0
stop结束索引(不包含)列表长度
step步长1

三个参数都可以省略,省略即取默认值。这种设计哲学很 Python:你不说的,它替你想好了。

正向索引

从左到右,从 0 开始:

1
2
3
4
5
6
fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
#  索引:    0       1       2       3       4

fruits[1:4]   # ["香蕉", "橙子", "葡萄"]
fruits[:3]    # ["苹果", "香蕉", "橙子"]
fruits[2:]    # ["橙子", "葡萄", "西瓜"]

负索引

从右到左,从 -1 开始。像是站在列表末尾往回看——有时候回头看,反而更清楚要取哪些。

1
2
3
4
5
6
fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
# 负索引:   -5      -4      -3      -2      -1

fruits[-3:]   # ["橙子", "葡萄", "西瓜"]  取最后3个
fruits[:-2]   # ["苹果", "香蕉", "橙子"]  去掉最后2个
fruits[-3:-1] # ["橙子", "葡萄"]          从倒数第3到倒数第2

索引对照图

元素:     ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
正索引:      0       1       2       3       4
负索引:     -5      -4      -3      -2      -1

正负索引指向同一个元素,只是观察的方向不同。正索引是从起点出发数步数,负索引是从终点倒着量距离。两套坐标系,一张地图。

步长的使用

1
2
3
4
5
6
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

nums[::2]    # [0, 2, 4, 6, 8]     每隔一个取一个
nums[1::2]   # [1, 3, 5, 7, 9]     从索引1开始,每隔一个
nums[::-1]   # [9, 8, 7, ..., 0]   反转列表
nums[7:2:-1] # [7, 6, 5, 4, 3]     逆向切片

实践应用

应用一:保留最近 N 条记录

在对话系统中,控制历史消息长度:

1
2
3
4
5
6
messages = ["消息1", "消息2", "消息3", "消息4", "消息5"]
max_history = 3

# 只保留最近 3 条消息
history = messages[-max_history:]
# history = ["消息3", "消息4", "消息5"]

记忆有限,只留最近的。这一行切片做的事情,和人脑的遗忘曲线倒有几分相似。

应用二:复制列表

1
2
original = [1, 2, 3]
copy = original[:]  # 浅拷贝,创建新列表

应用三:反转列表

1
2
text = "Hello"
reversed_text = text[::-1]  # "olleH"

应用四:分页处理

1
2
3
4
5
6
data = list(range(100))
page_size = 10
page = 3

# 获取第 3 页数据(索引 20-29)
page_data = data[(page-1)*page_size : page*page_size]

注意事项

切片不会越界

1
2
3
nums = [1, 2, 3]
nums[10:20]  # []  不报错,返回空列表
nums[-100:]  # [1, 2, 3]  等同于整个列表

索引取值越界会报 IndexError,但切片不会。它只是沉默地返回能给你的那部分,给不了的,就给一个空列表。这种宽容在别的语言里并不常见。

切片返回新列表

1
2
3
4
5
original = [1, 2, 3]
sliced = original[1:]

sliced[0] = 99
print(original)  # [1, 2, 3]  原列表不变

字符串也支持切片

1
2
3
text = "Python"
text[0:2]   # "Py"
text[-3:]   # "hon"

要点总结

  • 切片语法:list[start:stop:step]
  • 负索引从 -1 开始,表示列表末尾
  • list[-n:] 取最后 n 个元素
  • list[:-n] 去掉最后 n 个元素
  • list[::-1] 反转列表
  • 切片不会越界报错,返回空列表或可用部分
  • 切片返回新列表,不修改原列表

参考资料


两个冒号之间,藏着取舍的全部学问。写到这里忽然想起《老子》那句:「为学日益,为道日损。」切片的设计恰好反过来——语法越损(省略),能做的事越益(丰富)。大概好的工具都是这样:用最少的符号,表达最多的意图。