Effective Python(5): 了解切割序列的方法
2019-09-28 本文已影响0人
warmsirius
一、什么是切片?
Python提供了把序列切成小块的写法。这种切片操作,可以实现访问序列中某些元素所构成的子集。
最简单的用法,就是对内置的list、str和bytes进行切割。
注意: 切割操作还可以延伸到实现
__getitem
和__setitem
这两个特殊方法的Python类上。
二、切片的使用
1. 基本写法
somelist[start:end]
-
start
: 起始索引,所指的元素涵盖在切割后的范围内 -
end
: 结束索引,所指的元素不包括在切割结果之中
举例:
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('First four:', a[:4])
print('Last four', a[-4:])
print('Middle two', a[3:-3]
# 结果
First four: ['a', 'b', 'c', 'd']
Last four: ['e', 'f', 'g', 'h']
Middle two: ['d', 'e']
原则1:如果要从列表开头获取切片,那就不要在start
那里写上0,而应该留空
assert a[:5] == a[0:5]
原则2:如果切片要一直取到列表末尾,那就应该把end
留空
assert a[5:] == a[5: len(a)]
原则3:指定切片起止索引时,若要从列表尾部向前算,则使用负值表示相关偏移量
a[2: -1]
注意1: 值小的位置元素永远能取到,值大的位置元素永远取不到,正负一样道理。
注意2: 如果使用负变量作为start
索引来切割列表,如果start
=0时,表达式somelist[-0:]
则成了原列表的一份拷贝。
原则4:切割列表时,即便start
或end
索引越界也不会出问题
a[:20]
a[-20:]
注意: 访问列表中的单个元素时,下标不能越界,否则会导致异常
三、技术细节
1. 对原列表进行切割之后,会产生另外一份全新的列表。
系统依然维护这指向原列表中各个对象的引用。在切割后得到的新列表上进行修改,不会影响原列表。
2. 赋值时对左侧列表进行切割操作,会把该列表中处在指定范围内的对象替换为新值
- 与元组(
tuple
)的赋值(如a, b = c[:2]
)不同,列表切片赋值的长度无需新值个数相等。- 位于切片范围之前及之后的那些值都保留不变。列表会根据新值的个数相应地扩张或收缩。
3. 如果对赋值操作右侧的列表使用切片,而把切片的起止索引都留空,那就会产生一份原列表的拷贝
b = a[:]
assert b == a and b is not a
4. 如果对赋值操作左侧的列表使用切片,而又没有指定起止索引,那么系统会把右侧的新值复制一份,并用这份拷贝来替换左侧列表的全部内容,而不会重新分配新的列表。
b = [1, 2, 3]
b = a
a[:] = [101, 102, 103]
assert b is a
四、要点
- 不要写多余的代表:当
start
索引为0,或end
索引为序列长度时,应该将其省略 - 切片操作不会计较
start
与end
索引是否越界,使得我们很容易从序列的前端或后段开始,对其进行范围固定的切片操作。 - 对
list
赋值的时候,如果使用切片操作,就会把元列表中处在相关范围内的值替换成新值,即便它们的长度不同也依然可以替换。