在 Python 里,像列表(list)、元组(tuple)和字符串(str)这类 序列类型都支持切片操作,但是实际上切片操作比人们所想象的要强大很多。
在切片和区间操作里不包含区间范围的最后一个元素是 Python 的风格, 这个习惯符合 Python、C 和其他语言里以 0 作为起始下标的传统。这样 做带来的好处如下。
my_list[:x]
和 my_list[x:]
就可以了一个众所周知的秘密是,我们还可以用 s[a:b:c]
的形式对 s 在 a 和 b 之间以 c 为间隔取值。c 的值还可以为负,负值意味着反向取值。
a:b:c
这种用法只能作为索引或者下标用在 [] 中来返回一个切片对 象:slice(a, b, c)
。对 seq[start:stop:step]
进行求值的时候,Python 会调用 seq.__getitem__(slice(start, stop, step))
。
numpy.ndarray
就可以用 a[i, j]
这种形式来获取,抑或是用 a[m:n, k:l]
的方式来得到二维切片。
__getitem__
和 __setitem__
需要以元组的形式来接收 a[i, j]
中的索引。也就是说,如果要得到 a[i, j]
的值,Python 会调用 a.__getitem__((i, j))
。
如果把切片放在赋值语句的左边,或把它作为 del 操作的对象,我们就 可以对序列进行嫁接、切除或就地修改操作。
l = list(range(10))
--> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
l[2:5] = [20, 30]
--> l [0, 1, 20, 30, 5, 6, 7, 8, 9]
del l[5:7]
--> l [0, 1, 20, 30, 5, 8, 9]
l[3::2] = [11, 22]
--> l [0, 1, 20, 11, 5, 22, 9]
l[2:5] = [100]
--> l [0, 1, 100, 22, 9]
如果赋值的对象是一个切片,那么赋值语句的右侧必须是个可迭代 对象。即便只有单独一个值,也要把它转换成可迭代的序列。