今天你 AI 赋能了吗?打开浏览器,在地址栏输入 xuefulu.ai ,按下 Enter 即可访问学府路1号!
2026年10月14日 星期三 10:40:18
常用网址: | | 学府路1号 https://xuefulu.ai | 下载 Python https://xuefulu.ai/Python.html | 下载 TRAE https://xuefulu.ai/Trae.html

一、切片是什么(取一段)

切片(slice)就是从一个序列里「切下一段」。比如有一张歌单,你只想拿前三首,不用一个个写,用切片一句话搞定:

Python
songs = ['夜曲', '晴天', '稻香', '七里香', '告白气球']
first_three = songs[0:3]
print(first_three)

输出:

输出
['夜曲', '晴天', '稻香']

切片不只用于列表,字符串、元组一样能用。它最大的好处是:不用循环、不用数下标,一行就把「第几个到第几个」取出来。

你熟悉的写法切片写法
一个个赋值取前三首songs[0:3]
循环打印字符串前 5 个字符word[:5]
把列表倒过来lst[::-1]
切片取出来的是一份新的序列,不会改原来的数据。后面「常见坑」一节会专门讲这一点。

课程思政|数据安全与法治素养 · 取数据,只取该取的那一段

切片的妙处,是让你「只要前面一小段」的时候,不必把整个序列都端出来。这个思路在真实工作里同样成立:做报表常常只需要某几列、某几天,其余的姓名、身份证号本就不该被带走。够用就好,能少取就少取。最小必要不只是合规上的要求,也是替别人守住隐私的习惯。

二、三步写法 [起点:终点:步长](含头不含尾)

切片用方括号,里面最多写三项,用冒号隔开:

输出
序列[起点:终点:步长]

三项分别是什么

位置名字默认值含义
第 1 项起点0(开头)从哪个下标开始取(包含)
第 2 项终点末尾取到哪个下标之前(不包含)
第 3 项步长1每次跳几格;正数往前、负数往后

最重要的规则:含头不含尾

songs[0:3] 表示从下标 0 开始,取到下标 3 之前——也就是取下标 0、1、2,不取 3。

Python
scores = [60, 75, 82, 90, 100]
print(scores[1:4])

输出:

输出
[75, 82, 90]

下标 1 是 75、2 是 82、3 是 90,但终点 4 不含,所以取到 90 就停。取下标 1、2、3 三个元素。

「终点不包含」是切片最容易出错的地方。想取到下标 n(含),终点就要写 n+1;想取前 n 个,终点写 n 就行。比如取前 3 个写 [:3],取前 5 个写 [:5]。
口诀:起点要,终点不要。写 [a:b] 心里默念「从 a 取到 b 前面一个」。

三、四种最常用写法

把三项省略成几种最常用的组合,记住这四种就够用了:

写法含义例子(对 [0,1,2,3,4,5])
[:]从头到尾全部得到 [0,1,2,3,4,5]
[a:b]从 a 取到 b 前[1:4] → [1,2,3]
[:b]从头取到 b 前[:3] → [0,1,2]
[a:]从 a 取到末尾[3:] → [3,4,5]

挨个跑一遍

Python
lst = [0, 1, 2, 3, 4, 5]
print(lst[:])
print(lst[1:4])
print(lst[:3])
print(lst[3:])

输出:

输出
[0, 1, 2, 3, 4, 5]
[1, 2, 3]
[0, 1, 2]
[3, 4, 5]
省略起点代表「从头」、省略终点代表「到尾」。[:] 常用来复制一整个列表(拿到的是新的一份)。

四、负数下标

下标除了从 0 从左往右数,还能用负数从右往左数:-1 是最后一个,-2 是倒数第二个……

Python
pets = ['旺财', '咪咪', '豆豆', '团子', '雪球']
print(pets[-1])
print(pets[-2:])

输出:

输出
雪球
['团子', '雪球']

pets[-2:] 表示从倒数第二个开始,取到末尾——正好是最后两个。

写法取到什么
[-1]最后一个元素
[-3:]最后三个元素
[:-1]除最后一个以外的全部
[-3:-1]倒数第三到倒数第二(不含最后一个)
Python
s = 'abcdef'
print(s[-4:-1])

输出:

输出
cde
负数下标不用去算「长度减几」,直接「从右边数第几个」就行,特别适合「拿最后几个」的场景。

五、步长([::2]、[::-1] 反转)

第三项是步长:每隔几格取一个。写成 序列[起点:终点:步长]。

① 每隔一个取(步长 2)

Python
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nums[::2])

输出:

输出
[1, 3, 5, 7, 9]

② 反转序列(步长 -1)

Python
queue = ['小满', '阿离', '大可', '团子', '咕噜']
print(queue[::-1])

输出:

输出
['咕噜', '团子', '大可', '阿离', '小满']

③ 倒着每隔一个取(步长 -2)

Python
levels = ('青铜', '白银', '黄金', '铂金', '钻石', '星耀', '王者')
print(levels[::-2])

输出:

输出
('王者', '钻石', '黄金', '青铜')
步长效果
2每隔一个取,正着走
3每三个取一个
-1整个反转
-2反转后每隔一个取
步长为 0 是不允许的,会直接报错(详见「报错手册」)。想反转就写 -1,别写成 0。
记住 [::-1] 这个写法:它是 Python 里反转序列最常用的一招,字符串、列表、元组通吃。

AI 助手小贴士|负步长是切片最难啃的一口,让 AI 一步步推导。

打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:s[3:1:-1] 会取到哪些字符?请按 step 为负时 start 和 stop 的含义一步步推导,再出 2 道反向切片题考我

课程思政|工匠精神与严谨求实 · 方向写反,越取越空

步长的正负决定了走的方向:用负数步长时,起点必须比终点大,否则一个元素都取不到,只能对着空结果发呆。这类参数最怕凭印象写,多想一步「从哪往哪走、到哪停」,往往比改十次代码都省事。先想清楚规则,再动手敲,这份耐心正是严谨求实的底色。

六、超出范围不报错(和索引越界对比)

切片一个很友好的特点是:下标超出范围也不会报错,它会自动截到序列末尾。

Python
lst = [1, 2, 3]
print(lst[1:10])    # 终点 10 远超长度,只取到末尾

输出:

输出
[2, 3]

这和「单个下标」完全不同

写法结果
lst[1:10](切片)不报错,返回 [2, 3]
lst[5](单个下标)报错 IndexError

单个下标访问越界会崩,但切片越界只是「能拿多少拿多少」。这是因为切片本来就是为了「安全地取一段」。

Python
lst = [1, 2, 3]
print(lst[5])        # 下标 5 不存在
报错
IndexError: list index out of range
所以当你「不确定数据有多长、只想拿前面一段」时,切片比单个下标安全得多:data[:100] 即使不足 100 个也不会错。

七、字符串/列表/元组都通用(返回同类型)

切片的写法在字符串、列表、元组上完全一样,而且返回的类型和原来一致:字符串切片还是字符串,元组切片还是元组。

Python
# 字符串切片,结果仍是字符串
word = 'strawberry'
print(word[:3])

输出:

输出
str

元组的例子(返回还是元组)

Python
week = ('周一', '周二', '周三', '周四', '周五', '周六', '周日')
print(week[2:5])

输出:

输出
('周三', '周四', '周五')

字符串取中间一段

Python
slogan = '今天也要元气满满'
print(slogan[4:8])

输出:

输出
元气满满
原类型切片结果类型例子
列表列表lst[1:3] → 列表
字符串字符串s[1:3] → 字符串
元组元组t[1:3] → 元组
「返回同类型」很关键:对字符串切片得到的是子串(还能继续当字符串用),对元组切片得到的是新元组(不能改,但能读)。

八、切片不改原对象,重新赋值才改(lst[1:3] = [...])

用切片读取一段,原来的序列不会变,得到的是一份新的:

Python
a = [1, 2, 3]
b = a[1:3]        # 切出一段
b[0] = 99         # 改 b
print('a =', a)
print('b =', b)

输出:

Python
a = [1, 2, 3]
b = [99, 3]

改了 b,a 纹丝不动。说明切片返回的是新的副本。

想改原列表,要「重新赋值」

Python
lst = [1, 2, 3, 4, 5]
lst[1:3] = [9, 9, 9]    # 用切片当「位置」做替换
print(lst)

输出:

输出
[1, 9, 9, 9, 4, 5]

这里把下标 1、2 两个位置,换成了三个新元素,所以列表反而变长了。注意:这是「赋值给切片」,和「读切片」是两回事。

区分两种写法:b = a[1:3] 是「读」,原列表不变;a[1:3] = [...] 是「写」,会改原列表。少写一个等号,意思差很多。
想复制整个列表用 new = old[:]。比起 new = old(两个变量指向同一个列表),[:] 才是一份真正独立的副本。

课程思政|诚信与职业操守 · 副本上改,底稿要干净

b = a[1:3] 是「读」,原列表纹丝不动;a[1:3] = ... 是「写」,才会改到原表。少一个等号,意思差很多。处理真实数据也该这样:分析和修改都在副本上做,原始底稿保持原样,谁改过、改了什么都留得下痕迹。底稿干净,结论才站得住——这是技术习惯,也是做事的诚信。

九、实战:读一张身份证号(索引+切片+正负下标)

身份证号是一个 18 位的定长字符串,每一位都有固定含义。它是练索引和切片最合适的例子:长度固定、每一位都不多余,取哪一段、从哪边数,一验就知道对不对。下面先把「第几位」和「下标是多少」对上号。

先看这张位序表

从左往右数用正索引(从 0 开始),从右往左数用负索引(从 -1 开始):

身份证号440583198704201234
正索引01234567891011121314151617
负索引-18-17-16-15-14-13-12-11-10-9-8-7-6-5-4-3-2-1

出生年 · 索引 6~9出生月 · 索引 10~11出生日 · 索引 12~13后四位 · 索引 14~17

三个最容易记错的点:正索引从 0 开始(第 1 位对应下标 0);负索引从 -1 开始(最后一位是 -1);「第 N 位」永远比下标大 1——比如第 17 位的下标是 16。

18 位分成四段,每段管一件事

位次长度切片写法含义
第 1~6 位6id_no[:6]地址码(省、市、县)
第 7~14 位8id_no[6:14]出生年月日,8 位数字
第 15~17 位3id_no[14:17]顺序码,其中第 17 位表示性别
第 18 位1id_no[-1]校验码,可能是 0~9 或 X

下面用示例号码 440583198704201234 演示,它是虚构的:44 开头代表广东省、4405 是汕头市,再往后的区县编码和生日都只是凑数,不必当真。

取出生年月日、后四位、地址码

三段要的信息,三行切片就能取出来:

Python
id_no = '440583198704201234'

print(id_no[0:6])     # 前六位:地址码
print(id_no[6:14])    # 出生年月日,8 位
print(id_no[-4:])     # 后四位(含校验码)

输出:

输出
440583
19870420
1234

回忆一下「含头不含尾」:[6:14] 取的是下标 6 到 13,正好 8 个字符。要是取出来少一位或多一位,先回上面那张位序表数一遍下标。

正索引和负索引,取的是同一段

Python
id_no = '440583198704201234'

print(id_no[6:14], id_no[-12:-4])
print(id_no[14:], id_no[-4:])
print(id_no[16], id_no[-2])

输出:

输出
19870420 19870420
1234 1234
3 3

三组结果一一对应。负索引的好处是不用知道总长度——取后四位就写 [-4:],比先数到 18 再写 [14:] 省心,号码长一点短一点都照样管用。而「从第 7 位取到第 14 位」这种落在中间的一段,正索引更直观:[6:14] 一眼看清从哪儿到哪儿。

判断性别:看第 17 位的奇偶

第 17 位(也就是下标 16,或者从右数的 [-2])是性别位:奇数表示男,偶数表示女。把这个字符取出来转成整数,再判断奇偶:

Python
id_no = '440583198704201234'

gender = int(id_no[16])     # 第 17 位,等价写法 id_no[-2]
print('男' if gender % 2 else '女')

输出:

输出
男

gender % 2 余 1 为真、余 0 为假,正合「奇男偶女」,所以一个三元表达式就够了。换一个倒数第二位是偶数的号码试试:

Python
for id_no in ['440583198704201234', '440583198704201246']:
    code = int(id_no[16])
    print(code, '→', '男' if code % 2 else '女')

输出:

输出
3 → 男
4 → 女

最后一位可能是 X,它代表 10

第 18 位是校验码,由前 17 位按固定权重算出来,结果可能落在 0~9,也可能是字母 X。为什么会有 X?因为算出来的值有时正好是 10,一位放不下「10」,就用罗马数字 X 顶上。所以最后一位不能想当然地当数字用——直接转整数,遇到 X 当场就崩:

Python
id_no = '44058319870420123X'
print(int(id_no[-1]))
报错
ValueError: invalid literal for int() with base 10: 'X'

办法是先看是不是 X:是就按 10 处理,不是再转整数。

Python
id_no = '44058319870420123X'

last = id_no[-1].upper()          # 统一成大写,输入不规范时也认
value = 10 if last == 'X' else int(last)
print(last, '代表', value)

输出:

输出
X 代表 10

还有个细节:取性别位不会遇到这个问题——第 17 位一定是数字,会出 X 的只有最后一位。

连起来:一次读出全部信息

把上面几段拼一起,一条一条打印,正好对应四段结构:

Python
id_no = '440583198704201234'

print('地址码:', id_no[:6])
print('出生日期:', f'{id_no[6:10]}-{id_no[10:12]}-{id_no[12:14]}')
print('顺序码:', id_no[14:17])
print('性别:', '男' if int(id_no[16]) % 2 else '女')
print('校验码:', id_no[-1])

输出:

输出
地址码: 440583
出生日期: 1987-04-20
顺序码: 123
性别: 男
校验码: 4

两个提醒:一是示例号码是虚构的,只用来演示位置;真实号码属于个人敏感信息,写练习一律用编的号码,别拿别人的顶替。二是第 18 位的校验码由前 17 位按固定权重算出,可能是 0~9 也可能是 X——示例里的末位只是占位,不用去对算法。

十、十个基础案例(对应课堂 10 个例子)

下面 10 个案例都来自课堂讲解的切片示例,每个都真跑过。注意第 2 个例子里那个前导空格。

案例 1:取列表前三个

Python
animations = ['火影忍者', '海贼王', '名侦探柯南', '灌篮高手', '龙珠']
print(animations[0:3])

输出:

输出
['火影忍者', '海贼王', '名侦探柯南']

案例 2:取句子的后半部分

Python
sentence = 'good afternoon my friend'
print(sentence[14:])

输出:

输出
 my friend

注意:输出开头有一个空格!因为下标 14 正好落在 'afternoon' 后面的那个空格上。示例里常漏写这个空格,记住它是真实存在的。

案例 3:取元组中间几个

Python
week = ('周一', '周二', '周三', '周四', '周五', '周六', '周日')
print(week[2:5])

输出:

输出
('周三', '周四', '周五')

案例 4:反转列表

Python
queue = ['小满', '阿离', '大可', '团子', '咕噜']
print(queue[::-1])

输出:

输出
['咕噜', '团子', '大可', '阿离', '小满']

案例 5:每隔一个取

Python
ranks = ['青铜', '白银', '黄金', '铂金', '钻石', '星耀', '王者']
print(ranks[::2])

输出:

输出
['青铜', '黄金', '钻石', '王者']

案例 6:取最后两个

Python
menu = ['螺蛳粉', '麻辣烫', '烧烤', '炸鸡', '奶茶']
print(menu[-2:])

输出:

输出
['炸鸡', '奶茶']

案例 7:截取单词前三个字符

Python
word = 'strawberry'
print(word[:3])

输出:

输出
str

案例 8:步长 -2 反转取

Python
levels = ('青铜', '白银', '黄金', '铂金', '钻石', '星耀', '王者')
print(levels[::-2])

输出:

输出
('王者', '钻石', '黄金', '青铜')

案例 9:从中间到末尾每隔一个

Python
temps = [18, 20, 22, 24, 26, 28, 30, 32, 34]
print(temps[4::2])

输出:

输出
[26, 30, 34]

案例 10:截取长字符串中间一段

Python
lyric = '我想去看海边的日出和日落'
print(lyric[4:9])

输出:

输出
海边的日出

AI 助手小贴士|切片要练到「看结果写表达式」的条件反射。

打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:出 5 道写切片的题:给我字符串和想要的结果(比如从「Python」里取出「tho」),让我写切片表达式,写完对答案

十一、常见坑(步长 0、负数步长方向、浅复制)

坑 1:步长写成 0

Python
nums = [1, 2, 3]
print(nums[::0])
报错
ValueError: slice step cannot be zero

步长不能是 0(每跳 0 格永远停在原地,没意义)。想反转用 -1。

坑 2:负数步长的方向搞反

用负数步长时,起点要比终点大,否则什么都取不到:

Python
s = 'hello'
print(s[3:0:-1])     # 从 3 往回走到 1

输出:

输出
lle

s[3:0:-1]:从下标 3 开始,往回走(步长 -1),到下标 0 之前停,所以取 3、2、1,得到 'lle'。如果写成 s[0:3:-1] 反而取不到东西,因为起点 0 比终点 3 小、却又用负步长往回走,矛盾了。

坑 3:以为切片改了原对象

Python
a = [1, 2, 3]
b = a[:]
b[0] = 99
print(a)        # a 没变

输出:

输出
[1, 2, 3]

用 a[:] 复制后改副本,原列表不受影响。只有 a[1:3] = ...(把切片写在等号左边)才会改原列表。

坑 4:切片是「浅」复制

Python
a = [[1, 2], [3, 4]]
b = a[:]          # 复制外层列表
b[0][0] = 99      # 改内层列表的元素
print(a)

输出:

输出
[[99, 2], [3, 4]]

切片只复制了外层,里面嵌套的列表还是同一份。改了 b[0] 里的内容,a 也跟着变。嵌套结构要小心这点。

坑 5:「第 N 位」不是「下标 N」

身份证号第 17 位是性别位,很多人顺手就写 id_no[17]——拿到的其实是第 18 位。这一类错误不会报错,只是结果悄悄错了,最难查:

Python
id_no = '440583198704201234'

print('第 17 位:', id_no[17])    # 错:这是第 18 位
print('第 17 位:', id_no[16])    # 对

输出:

输出
第 17 位: 4
第 17 位: 3

两个数字都合法,程序照跑不误,但性别判反了。口诀记牢:下标 = 第几位 − 1;拿不准就回头看位序表。

最容易混的是:lst[1:3](读,返回新列表)和 lst[1:3] = [...](写,改原列表)。写代码时盯一下等号在不在切片左边。

十二、报错手册

切片相关的报错不多,下面都是真跑出来的原文。

① 步长为 0

Python
nums = [1, 2, 3]
print(nums[::0])
报错
ValueError: slice step cannot be zero

原因:步长不能是 0。想反转用 -1,想隔一个用 2。

② 单个下标越界(注意:切片越界不报这个)

Python
lst = [1, 2, 3]
print(lst[5])
报错
IndexError: list index out of range

原因:用单个下标访问不存在的位置会崩。如果只想「尽量取一段」,用切片 lst[3:100] 就不会错。

③ 对象不支持切片

Python
n = 10
print(n[1:3])
报错
TypeError: 'int' object is not subscriptable

原因:只有序列(字符串/列表/元组等)才能切片,单个数字 10 不行。

④ 下标或步长不是整数

Python
lst = [1, 2, 3]
print(lst[1:3.0])
报错
TypeError: slice indices must be integers or None or have an __index__ method

原因:切片的起点、终点、步长都必须是整数,3.0 这种浮点数不行(哪怕它的值等于 3)。

⑤ 校验码是 X,转整数就崩

Python
id_no = '44058319870420123X'
print(int(id_no[-1]))
报错
ValueError: invalid literal for int() with base 10: 'X'

原因:int() 只认数字字符,'X' 不是。身份证号最后一位可能是 X(代表校验值 10),碰到它就先用 if 拦一下:是 X 就当 10 处理,否则再转整数。

AI 助手小贴士|负索引和步长是切片最容易晕的地方。让 AI 从三个参数的含义一步步推导,比死记结论扎实。

打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:s[::-1] 为什么能反转字符串?请从切片 start、stop、step 三个参数的含义讲起,再出 3 道切片题考我(要包含负索引和步长)

十三、随堂自测(12 题)

点击选项即可判分,选错的题会立刻展开解析。做完可以看到正确率和错题清单,也可以重新答题。

已答 0 / 12 · 正确 0 —

1[1,2,3,4,5][1:4] 取到的是哪些下标对应的元素?

  • A. 下标 0、1、2
  • B. 下标 1、2、3
  • C. 下标 1、2、3、4
  • D. 下标 2、3、4
答案:B。切片含头不含尾:起点 1 取、终点 4 不取,所以取下标 1、2、3 三个元素,结果是 [2,3,4]。

2[10,20,30,40,50][2:5] 的结果是什么?

  • A. [20,30]
  • B. [20,30,40,50]
  • C. [30,40,50]
  • D. [40,50]
答案:C。起点 2(值 30)取,终点 5(不存在,视为末尾)不取,取到 30、40、50,结果 [30,40,50]。

3lst[:] 表示取什么?

  • A. 从头到尾整个序列
  • B. 一个空序列
  • C. 只有最后一个元素
  • D. 会报错
答案:A。省略起点和终点就是「从头到尾」。lst[:] 常用来复制整个列表,得到一份独立的新副本。

4nums[::2] 里的步长 2 是什么意思?

  • A. 只取前两个元素
  • B. 倒着取一遍
  • C. 每隔一个取一个
  • D. 只取第一个元素
答案:C。步长为 2 表示「每跳两格取一个」,对 [1,2,3,4,5] 会得到 [1,3,5]。想反转要写负步长 -1。

5想把列表 lst 反转,最常用的是?

  • A. lst[::2]
  • B. lst[::-1]
  • C. lst[-1::]
  • D. lst[:0:-1]
答案:B。[::-1] 是 Python 反转序列的标准写法:步长 -1 从尾走到头,字符串、列表、元组都能用。

6想取列表 lst 的最后两个元素,正确的是?

  • A. lst[:2]
  • B. lst[-2::]
  • C. lst[:-2]
  • D. lst[-2:]
答案:D。lst[-2:] 表示从倒数第二个取到末尾,正好是两个;[:-2] 反而是「除最后两个外全部」。

7切片时终点下标超出了序列长度,会发生什么?

  • A. 不报错,自动截到末尾
  • B. 报 IndexError
  • C. 返回 None
  • D. 只取到倒数第二个
答案:A。切片越界很友好,能拿多少拿多少、不会报错;但单个下标越界(如 lst[5])才会报 IndexError。

8用单个下标访问 lst[5],但列表只有 3 个元素,会怎样?

  • A. 返回 None
  • B. 返回最后一个元素
  • C. 不报错返回空
  • D. 报 IndexError
答案:D。单个下标访问不存在的位置会报 IndexError: list index out of range;想安全取一段要用切片 lst[3:100]。

9写 nums[::0](步长为 0)会怎样?

  • A. 返回一个空列表
  • B. 报 ValueError: slice step cannot be zero
  • C. 返回原序列
  • D. 报 SyntaxError
答案:B。步长不能是 0(每跳 0 格没有意义),会报 ValueError。反转请写 -1,隔一个取写 2。

10用切片读取 b = a[1:3] 之后,再改 b,原列表 a 会怎样?

  • A. 也会被改
  • B. 报错
  • C. 不会被改,返回的是新对象
  • D. 两个都变成空
答案:C。读切片返回的是新的副本,改 b 不影响 a。只有把切片写在等号左边(a[1:3] = ...)才会改原列表。

11身份证号 id_no = '440583198704201234',想取出出生年月日(19870420),下面哪个写法对?

  • A. id_no[6:14]
  • B. id_no[7:15]
  • C. id_no[6:13]
  • D. id_no[-12:]
答案:A。出生年月日在第 7~14 位,下标范围是 6~13,按「含头不含尾」写 id_no[6:14]。[7:15] 整体后移一位,[6:13] 少取一位,[-12:] 等于 [6:],会把后四位也带上(得到 12 个字符)。

12某个身份证号最后一位是 X,执行 int(id_no[-1]) 会怎样?

  • A. 返回 0
  • B. 返回 10
  • C. 返回 None
  • D. 报 ValueError: invalid literal for int() with base 10: 'X'
答案:D。int() 只接受数字字符,'X' 会被判定为非法字面量并抛异常。X 代表校验值 10,正确做法是先判断:10 if id_no[-1].upper() == 'X' else int(id_no[-1])。