PythonI/O进阶学习笔记_4.自定义序列类(序列基类继承关系/可切片对象/推导式)

前言:本文代码基于python3Content:1.python中的序列类分类2.python序列中abc基类继承关系3.由list的extend等方法来看序列类的一些特定方法4.list这种序列类的一大特点:切片。和如何实现可切片对象。到如何自定义一个序列类。5.biset维护排序序列6.什么时候使用list7.列表推导式、生成器表达式、字典推导式1.python中的序列类分类a.什么是pyth...

PythonI/O进阶学习笔记_4.自定义序列类(序列基类继承关系/可切片对象/推导式)

前言:

本文代码基于python3

Content:

1.python中的序列类分类

2. python序列中abc基类继承关系

3. 由list的extend等方法来看序列类的一些特定方法

4. list这种序列类的一大特点:切片。和如何实现可切片对象。到如何自定义一个序列类。

5. biset维护排序序列

6. 什么时候使用list

7.列表推导式、生成器表达式、字典推导式

1.python中的序列类分类

a.什么是python的序列类?

之前提到的魔法函数这种时候就很重要啦。满足序列类相关的协议就称为python里的序列类。python内置的序列类有dict、tuple、list等。

而我们自定义序列类的话,由于魔法函数的存在。序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列。

b.python按分类来看有哪些序列类?

- 容器序列:list,tuple,deque(可以放任意的类型的容器)

- 扁平序列:str,bytes,bytearray,array.array(可以使用 for循环遍历的)

- 可变序列:list,deque,bytearray,array

- 不可变:str,tuple,bytes

ps.这里推荐一本书 fluent python

Python标准库提供了大量使用C来实现的序列类型,

从序列中的元素类型是否一致作为标准,包括容器序列(Container sequences,包括list、tuple、collections.deque等)和固定序列(Flat sequences,包括str、bytes、bytearray、memoryview、array.array)等。

ps.容器序列中实际存放的元素是对其他任意对象的引用,而固定序列中存放是真正的是元素值,因此所有的元素必须是相同类型,并且只能是Python基本类型(字符、字节、数字等)的数据。

如果从序列中的元素是否能够被修改的标准来看,Python的序列类型又分为可变序列(Mutable sequences,包括list、bytearray、array.array、collections.deque、memoryview等)和不可变序列(Immutable sequences,包括tuple、str、bytes等)

c.序列常见操作

索引(index)分片(slicing)序列相加(拼接)乘法(重复)成员资格(in)长度(len)max()min()可以迭代
sortedenumeratezipfiltermap

2. python序列中的abc继承关系

在python的collection模块中,有abc模块,和容器相关的抽象基类和数据结构都在其中。

那么abc模块中,具体有哪些类呢?

其中,Sequence就是可变序列的方法集合的抽象基类,MutableSequence是集合了不可变序列的方法和协议的抽象基类。

这些抽象类之间的关系:

a.可变序列(MutableSequence)从不可变序列(Sequence)那里继承了一些方法.

b.Sequence继承了collection,collection又继承了Sized、Container、Iterable

c.python的内置序类型并没有直接继承这些基类,但是这些基类定义了某种特性序列的方法和协议,了解这些基类间的继承关系能很好的帮助我们了解python的内置序列类型。

综上可得图:

3.由list的extend等方法来看序列类的一些特定方法调用

对list序列进行添加操作一般有几种方法?

、 =、extend、append

这里有几个好玩的地方:

a. 和 =的区别

可以看到 =的对象可以是tuple,而 不可以。

实际上 =是调用了一个魔法函数 __iadd__实现的。使用 =的时候,实际上还是调用了extend方法。

extend传递的参数类型是可迭代类型,用for循环,它会遍历可迭代的类型,一个个加到列表里。

b.extend、append的区别

上面已经贴出了extend的实现,现在看append的实现:

很明显的一点,一个直接用insert把对象插入,一个遍历对象加入。

4. list这种序列类的一大特点:切片。和如何实现可切片对象。到如何自定义一个序列类。

a.python的切片的一些用法:

alist = [3,4,5,6,7,9,11,13,15,17]print(alist[::]) # 返回包含原列表中所有元素的新列表print(alist[::-1]) # 返回原列表的逆序排列print(alist[::2]) # 返回原列表的偶数位数据print(alist[1::2]) # 获取奇数位置的数据print(alist[3:6]) # 指定切片的开始和结束位置print(alist[0:100]) # 切片位置大于列表长度时,从列表尾部截断print(alist[100:]) # 切片开始位置大于列表长度时,返回空列表alist[len(alist):]=[9] # 在列表尾部增加元素print(alist)alist[:0] = [1,2] # 前面的0省略了,相当于是alist[0:0] = [1,2]print(alist)# 在列表的头部增加元素alist[3:3] =[4] # 在列表中间插入元素print(alist)alist[:3] = [1,2] # 相当于是alist[0:3] = [1,2] 替换列表元素alist[3:] = [4,5,6] # 替换元素,结果按照两边的最短元素来决定.print(alist)alist[:3] = []  # 删除列表中前三个元素del alist[:3] # 切片元素连续del alist[::2] # 隔一个删除一个,切片元素不连续

b.自己实现一个可切片的序列类(包括可切片、可添加等内置序列类型有的操作)

自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等)。

如果要实现这个功能,就要遵循 python 的相关的协议。所谓的协议就是一些约定内容。例如,如果要将一个类要实现迭代,可以实现__iter__()或者__getitem__()其中一个方法

例子:自定义一个可以被切片的Group类:

import numbersclass Group: # 支持切片操作 def __init__(self, group_name, company_name, staffs):  self.group_name = group_name  self.company_name = company_name  self.staffs = staffs def __reversed__(self):  self.staffs.reverse() # 因为object[] 和 object[::]都会调动这个方法 def __getitem__(self, item):  # 取到class  cls = type(self)  #判断传递进来的是slice类型还是int类型,返回不同的类型和操作,  if isinstance(item, slice):return cls(group_name=self.group_name, company_name=self.company_name,  staffs=self.staffs[item])  if isinstance(item, numbers.Integral):return self.staffs[item] def __iter__(self):  return iter(self.staffs) def __len__(self):  return len(self.staffs) def __str__(self):  return '组员有:{}'.format(self.staffs) def __contains__(self, item):  if item in self.staffs:return True  else:return Falsestaffs = ['tangrong1', '123', '456', '789']group = Group('A', 'TR', staffs=staffs)sub_group = group[:2]print(group)print(sub_group)if 'A' in group:  # 这里会调用__contains__魔
源文地址:https://www.guoxiongfei.cn/cntech/27157.html