切割序列类型的方法

切割序列类型的方法

  Python提供了列表切片的方法。这种切片(slice)操作,使开发者能够轻易地访问列表中某些元素。最简单的用法,就是对内置的list、str、bytes进行切割。切割操作还可以眼神到实现了__getitem__和__setitem__这两个类方法上。切割操作的基本写法是somelist[start:end],其中start是起始索引,end是结束索引,结束索引会自动减一。

 

一 切片基本使用

 

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(f'第1-4个值: {list1[:4]}') print(f'最后4个值: {list1[-4:]}') print(f'中间两个值: {list1[3: -3]}')
>>> 第1-4个值: ['a', 'b', 'c', 'd'] >>> 最后4个值: ['e', 'f', 'g', 'h'] >>> 中间两个值: ['d', 'e']

 

 

二 要点

① :start处不要写0  

  如果从列表开头获取值,start处不要写0,而是应该把它留空,这样代码看起来会清爽一些。

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
# 不报错就代表断言成功
assert list1[:5] == list1[0:5]

 

② :end处应该留空

  如果切片一直取到末尾,end处就应该留空,就算写了值也是多余的。

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
# 不报错就代表断言成功
assert list1[5:] == list1[5:len(list1)]

 

③ :start或end索引越界也不会出现问题

  在切割列表时,即便start或end索引越界也不会出现问题。我们可以利用这一特性,限定输入序列类型的最大长度。

# 切片越界不会报错
first_end = list1[:100]
last_end = list1[-100:]
print(first_end)
print(last_end)

# 注意: 切片start若为-0时,则会在原来列表中拷贝一份
last_end2 = list1[-0:]
print(last_end2)

# 反而访问列表中单个元素的时候,下标越界就会出现异常
print(list1[100])
# >>> IndexError: list index out of range

 

④ :对原列表进行切割之后, 会产生另外一份全新的列表。在切割后得到的新列表上进行修改,不会影响原列表。

# 切片过后的列表赋值给b
b = list1[4:]
print('修改前', b)

# 对b进行修改不会影响原列表list1
b[1] = 99
print('修改后', b)
print('', list1)

 

⑤ :在赋值时对左侧列表使用切割操作,会把该列表中处在指定范围内的值替换为新值。与元组的赋值不同,元组切片的长度必须个数相等。但是列表的切片长度无需个数相等。位于切片范围之前及之后的值都保留不变,列表会根据新值的个数相应地扩展与收缩。

# 元组切片赋值(元组切片的长度必须个数相等)
tuple1 = (1, 2, 3, 4, 5, 6, 7)
t1, t2, t3 = tuple1[:3]
print(t1, t2, t3)  # 1 2 3

t3, t4, t5 = tuple1[:2]
print(t3, t4, t5)
>>> ValueError: not enough values to unpack (expected 3, got 2)


# 列表切片赋值(列表切片的长度必须个数相等)
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('改变前', list1)

# 缩短
list1[:5] = [1, 2, 3]
print('改变后', list1)
>>> 改变前 ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> 改变后 [1, 2, 3, 'f', 'g', 'h']

# 扩张
list1[:5] = [1, 2, 3, 4, 5, 6,7]
print('改变后', list1)
>>> 改变前 ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> 改变后 [1, 2, 3, 4, 5, 6, 7, 'f', 'g', 'h']

 

⑥ :如果列表赋值操作的右侧列表使用切片,而且把切片的起、止位置都留空,则会产生一份原列表的拷贝。

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
list2 = list1[:]

# 值相等,但id不相等
assert list2 == list1 and list2 is not list1

 

⑦ :如果列表赋值操作的左侧使用切片,而没有指定起、止索引,那么就会把右侧列表拷贝一月份,将这份拷贝的值替换左侧列表中的全部内容,并且指向同一个内存地址,而不会重新分配新的列表。

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
list2 = list1
print('改变前: ', list2)
list1[:] = [1, 2, 3]

# 断言表示list1与list2的id相等
assert list1 is list2

print('改变后: ', list1)

>>> 改变前:  ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> 改变后:  [1, 2, 3]

 

总结: 

  1.不要写多余的代码: 当start索引为0, 或end索引为序列长度时,应该将其省略。

  2.切片操作不会计较start与end索引是否越界,这使我们很容易就能从序列的前或后开始,并对其进行范围固定的切片操作。

  3.对list赋值的时候,如果使用切片操作,就会把原列表中所处范围的值替换成新值,即便它们的长度不同也依然可以替换。

 

posted @ 2019-07-10 13:55  tank_jam  阅读(439)  评论(0)    收藏  举报