知乎问答之 Python 切片

这是一个知乎问答的补充。原问题是python中字符串 s[ : -1]是什么意思?,当时回答的内容只是对问题本身的简单回答,对 Python 切片中的重要信息是有所忽略的。如果以slice对象的方式进行切片的话,其语法是这样的:slice(start, stop[, step]),在原回答中把重要的step给忽略掉了,当然,题主也没有问到。但仍然很有必要把 Python 切片中的重要信息给补充上。所以,在这里重新整理一下 Python 切片相关知识,主要参考 Python 官方文档、博客文章、以及 Python 书籍《Python 编程快速上手 让繁琐工作自动化》和《Python 编程无师自通 专业程序员的养成》。

切片

切片是:将一个可迭代对象中元素的子集,创建为一个新的可迭代对象。可迭代对象包括所有序列类型,如基本序列类型:list, tuplerange 对象,以及特别定制的附加序列类型,strbytes。利用 Python 的切片功能可实现对序列的提取、倒序、浅复制和修改、删除元素的操作。

切片的实现方法

要实现切片有两种方法,一是索引扩展(Extending Indexing)的方式;二是slice对象的方式。语法如下所示:

索引扩展(Extending Indexing)

sequence [start:stop[:step]]

start
Optional. Starting index of the slice. Defaults to 0.
stop
Optional. The last index of the slice or the number of items to get. Defaults to len(sequence).
step
Optional. Extended slice syntax. Step value of the slice. Defaults to 1.

slice对象,其实方括号(下标/索引)标记在内部使用的就是 slice 对象。

sequence [slice(start, stop[, step])]

序列元素访问复习——索引

在开始切片之前,让我们先复习一下序列元素的访问。切片的其中一种方法是索引扩展(Extending Indexing),那么要访问序列的元素可以用索引,其实切片也是访问元素的一种,区别在于切片是返回序列,而索引是返回单个元素。

序列索引只能是整数,不能是浮点值。不然将导致 TypeError 错误。序列访问支持负数索引,即:可用来从右向左查找,可迭代对象中元素的索引(必须是一个负数)。整数值 −1 指的是 列表中的最后一个索引,−2 指的是列表中倒数第二个索引,以此类推,在这里重点注意,负数索引是向后查找,从右往左的,切片同样支持负数。如下图:

PYTHON切片角标 python切片怎么用_python

正式开始切片

切片时包含起始索引位置的元素,但不包括结束索引位置的元素,即[start,stop)。当start + 1 == stop时返回一个元素;当start == stop时返回一个空(empty)序列。

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[1:5] # ['b', 'c', 'd', 'e']
l[1:2] # ['b']
l[4:4] # []

PYTHON切片角标 python切片怎么用_索引_02


作为快捷方法,你可以省略切片中冒号两边的一个索引或两个索引。省略第一个索引相当于使用 0,或列表的开始。省略第二个索引相当于使用列表的长度,意味着切片直至列表的末尾。当两个都省略时,即返回一个原索引的浅复制(shallow copy)。

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[:3] # ['a', 'b', 'c']
l[0:3] # ['a', 'b', 'c']
l[4:] # ['e', 'f', 'g', 'h', 'i']
l[4:len(l)] # ['e', 'f', 'g', 'h', 'i']
l1 = l[:] # 浅复制
l is l1 # False

PYTHON切片角标 python切片怎么用_程序人生_03


切片中的负数索引,同样从右往左向后查找。

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[-7:-2] # ['c', 'd', 'e', 'f', 'g']
l[2:7] # ['c', 'd', 'e', 'f', 'g']
l[2:-5] # ['c', 'd']
l[-8:] # ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[:-1] # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

PYTHON切片角标 python切片怎么用_python_04


PYTHON切片角标 python切片怎么用_python_05

到现在为止,还没有为切片设定step值,其实是在使用默认值,默认值为1,即每次移动一个序列元素。如果想要跳过一些元素,就可以显式设定step的值。

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[2:7:2] # ['c', 'e', 'g']

PYTHON切片角标 python切片怎么用_程序人生_06

同样的,step也支持负数,也是向后采集的意思。如果setp为负数,start值必须大于stop,不然将会得到一个空(empty)序列;如果省略start值,相当于从原序列的末尾开始,如果省略stop值,相当于从原序列的开始结束;而如果start值和stop值都省略,并把step值设置为1的话,将会得到一个反转的(reversed)序列。

l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[6:1:-2] # ['g', 'e', 'c']
l[1:6:-2] # []
l[:6:-1] # ['i', 'h']
l[6::-1] # ['g', 'f', 'e', 'd', 'c', 'b', 'a']
l[::-1] # ['i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']

PYTHON切片角标 python切片怎么用_程序人生_07

切片除了可以查找序列中的元素之外,还有一些重要的功能就是修改序列/元素、删除序列元素。

# 修改
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
l[1:4] = [1, 2, 3] # 修改后结果为:['a', 1, 2, 3, 'e', 'f', 'g', 'h', 'i']
l[1:2] = [1, 2, 3] # 修改/替换后的结果为:['a', 1, 2, 3, 2, 3, 'e', 'f', 'g', 'h', 'i']

# 插入
l = ['a', 'b', 'c']
l[:0] = [1, 2, 3] # 插入后结果为:[1, 2, 3, 'a', 'b', 'c']

l = ['a', 'b', 'c']
l[len(l):] = [1, 2, 3] # 插入后结果为:['a', 'b', 'c', 1, 2, 3]

l = ['a', 'b', 'c']
l[1:1] = [1, 2, 3] # 插入后结果为:['a', 1, 2, 3, 'b', 'c']

# 删除
l = ['a', 'b', 'c', 'd', 'e']
l[1:5] = [] # 删除后结果为:['a']

# 还可以用 del 语句删除序列中的部分元素
l = ['a', 'b', 'c', 'd', 'e']
del l[1:5] # 删除后结果为:['a'],效果一样

PYTHON切片角标 python切片怎么用_编程语言_08

以上都是**索引扩展(Extending Indexing)**的方法实现切片,现在再来看看slice对象。同样的,可以为其指定start值和stop值,step是一个可选参数,默认是1。要注意的是slice对象可以只给一个参数,这时就相当于[:stop],如果把这个参数设为None就相当于[:]

l = ['a', 'b', 'c', 'd', 'e']
s = slice(1, 5, 2) # slice(1, 5, 2)
s = slice(1, 5) # slice(1, 5, None)
s = slice(5) # slice(None, 5, None)
s = slice(None) # slice(None, 5, None)
s = slice(None) # slice(None, None, None)

PYTHON切片角标 python切片怎么用_索引_09


关于 Python 切片基本就整理到此,初学者使用切片可能容易出错。需要记住的是,负数从右向左查找;切片时包含起始索引位置的元素,但不包括结束索引位置的元素,即[start,stop);当你的stop不是预期时,可以设置为stop + 1或省略,尤其是step为负数的情况下;切片中的 index不会发生list index out of range的错误。以上可能有错漏的地方,欢迎指正。作为非大神,菜鸟一只的我,拍砖也恳请轻拍。

这次的 Python 切片整理是源于一个知乎问答,python中字符串 s[ : -1]是什么意思?,当时主要是摘录了两本书的相关章节内容,后面再慢慢搜索整理、补充。其实读书无论是对于新手还是老司机都是学习的好方法,这不,前段时间从阮一峰先生博客看到一个资源链接,于是也把里面的书单给整理出来了,可能是因为都是好书吧,基本上都能找到对应的中文版本。这其中还有两本免费的英文原版书,《Python Programming: An Introduction to Computer Science 》和《Learning With Python: How to Think Like a Computer Scientist》。

参考

Python 官方文档-术语表 slice

Python 官方文档-Python 标准库 内置函数 slice()

Python 官方文档-Python 语言参考 del 语句