30.2.2. 不要在切片里同时指定起止下标与步进

Python还有一种特殊的步长切片形式,即somelist[start:end:stride]。这种形式会在每n个元素里面选取一个,这样很容易就能把奇数位置上的元素与偶数位置上的元素分别通过x[::2]x[1::2]选取出来。

In [26]: x = ['red', 'orange', 'yellow', 'green', 'blue', 'purple']
    ...: odds = x[::2]   # 从下标0开始,每2个元素取一个(隔1个取1个)
    ...: evens = x[1::2] # 从下标1开始,每2个元素取一个
    ...: print(odds)
    ...: print(evens)
    ...:
    ...:
['red', 'yellow', 'blue']
['orange', 'green', 'purple']

Python里面有个技巧,把-1当成步长对bytes类型的字符串做切片,这样就能将字符串反转过来。

In [27]: x = b'mongoose'
    ...: y = x[::-1]
    ...:
    ...:

In [28]: y
Out[28]: b'esoognom'

Unicode形式的字符串也可以这样反转

In [29]: x = '月饼'
    ...: y = x[::-1]
    ...: y
    ...:
    ...:
Out[29]: '饼月

如果把这种字符串编码成UTF-8标准的字节数据,就会报错

使用起止下标与步长会让切片很难懂。 为了避免这个问题,建议大家不要把起止下标和步长同时写在切片里。 如果必须指定步长,那么尽量采用正数,而且要把起止下标都留空。即便必须同时使用步长值与起止下标,也应该考虑分成两次来写。

y = x[::2] # ['a', 'c', 'e', 'g']
z = y[1:-1] # ['c', 'e']

要点:

同时指定切片的起止下标与步进值理解起来会很困难。

如果要指定步进值,那就省略起止下标,而且最好采用正数作为步进值,尽量别用负数。

不要把起始位置、终止位置与步进值全都写在同一个切片操作里。如果必须同时使用这三项指标,那就分两次来做(其中一次隔位选取,另一次做切割),也可以改用itertools内置模块里的islice方法。