前言
一直想把Python切片的知识总结,但拖延至今方才摁键。起因是室友接受了导师给的课题,机器学习相关,之前他一直实习Java,现在要学Python了。有一天他发信息问我关于切片的问题,我竟不能十分肯定的回答。惭愧!但不得不说,Python切片中的Tips是我之前不曾见过,也自然不曾使用的,今日就着外面世界的烟火炮竹,把眼界大开。
切片
切片的完整格式:[start:end:step]
,通常我们只用到start,end。
这里引用Bobby老师的一段话,对切片格式简单介绍:
其中,第一个数字start表示切片开始位置,默认0;
第二个数字end表示切片截止(但不包含)位置(默认为列表长度);
第三个数字step表示切片的步长(默认为1)。
当start为0时可以省略,当end为列表长度时可以省略,
当step为1时可以省略,并且省略步长时可以同时省略最后一个冒号。
另外,当step为负整数时,表示反向切片,这时start应该比end的值大才行。
如果存在一个列表lyst = [1, 2, 3, 4]
,那么lyst[2:4]
的值为[3, 4]。对Python来说,切片并非列表专利,元组也可以做切片操作:
In [0]: tuple_ = (1, 2, 3, 4)
In [1]: tuple_[2:4]
Out[1]: (3, 4)
可看到一个现象,列表的切片类型是列表,元组的切片类型还是元组。
关于切片的一些常见使用如下:
In [0]: lyst = [1, 2, 3, 4]
In [1]: lyst[::]
Out[1]: [1, 2, 3, 4]
In [2]: lyst[::-1] # 反向序列
Out[2]: [4, 3, 2, 1]
In [3]: lyst[::2] # 等同“lyst[0::2]”。从索引0开始,每间隔一个元素取一个值。
Out[3]: [1, 3]
In [4]: lyst[1::2] # 从索引1开始,每间隔一个元素取一个值。
Out[4]: [2, 4]
In [5]: lyst[1:100] # end >= 列表长度时,可以省略end。等同“lyst[1:]”
Out[5]: [2, 3, 4]
In [6]: lyst[100:] # 当star >= 列表长度时,切片操作得到一个空列表
Out[6]: []
Tips
以下以lyst = [1, 2, 3, 4]
为例(下面操作中,等号右边必须是可迭代类型):
在列表最左边插入元素:
In [0]: lyst[:0] = ["z", "t", "y"] In [1]: lyst Out[1]: ['z', 't', 'y', 1, 2, 3, 4] In [2]: lyst[:0] = "512" In [3]: lyst Out[3]: ['5', '1', '2', 'z', 't', 'y', 1, 2, 3, 4]
在列表最右边插入元素:
In [0]: lyst[100:] = ["z", "t", "y"] In [1]: lyst Out[1]: [1, 2, 3, 4, 'z', 't', 'y'] In [2]: lyst[len(lyst):] = [512] In [3]: lyst Out[3]: [1, 2, 3, 4, 'z', 't', 'y', 512]
在列表中间插入元素:
In [0]: lyst[2:2] = ["zty"] # 将等号右边列表中的元素从索引为2的位置开始插入 In [1]: lyst Out[1]: [1, 2, 'zty', 3, 4] # "zty"的索引为2 In [2]: lyst[1:1] = "gyx" # 注意与 ["gyx"] 的区别 In [3]: lyst Out[3]: [1, 'g', 'y', 'x', 2, 'zty', 3, 4]
元素替换:
In [0]: lyst[1:2] = "z" In [1]: lyst Out[1]: [1, 'z', 3, 4] In [2]: lyst[2:] = [512, 1024, 2048] In [3]: lyst Out[3]: [1, 'z', 512, 1024, 2048]
隔位替换(等号右边的序列长必须等于等号左边的切片长):
In [0]: lyst[::2] = [0] * 2 In [1]: lyst Out[1]: [0, 2, 0, 4] In [2]: lyst[1::2] = "ty" In [3]: lyst Out[3]: [0, 't', 0, 'y']
删除元素:
In [0]: lyst[:2] = [] # 这种方式只能删除连续元素 In [1]: lyst Out[1]: [3, 4]
等同:
In [0]: del lyst[:2] In [1]: lyst Out[1]: [3, 4]
按一定规律删除间隔的元素:
In [0]: del lyst[::2] # 删除元素1,3 In [1]: lyst Out[1]: [2, 4]
实现切片
Python中,如果希望对象可以使用切片操作,需要实现__getitem__
方法。
from numbers import Integral
class Room(object):
def __init__(self, people=None):
people = people or []
self.people = people
def __getitem__(self, item):
print("item 的类型是 ", type(item))
# 获取索引位置的值
if isinstance(item, Integral):
return self.people[item]
# 确保切片出来的对象类型是切片之前的类型
return self.__class__(self.people[item])
def __str__(self):
return str(self.people)
if __name__ == "__main__":
room = Room(["bobby", "lily", "Joe", "Green"])
print(type(room[3]))
print(room[1:3])
print(type(room[1:3]))
# 输出:
item 的类型是 <class 'int'>
<class 'str'>
item 的类型是 <class 'slice'>
['lily', 'Joe']
item 的类型是 <class 'slice'>
<class '__main__.Room'>
可见,当括号中内容不是一个数值时,解释器会取出括号中的内容用来实例化slice类型的对象,然后传入__getitem__
方法中。此时,对item打印,输出如下:
# room[1:3]
slice(1, 3, None)
# room[1:4:2]
slice(1, 4, 2)
也就是说,slice类的初始化参数依次对应了start,end,step。
感谢
- 参考慕课Bobby老师课程Python高级编程和异步IO并发编程
还不快抢沙发