python中除list,dict,str外的其它序列数据结构
- 数组
- 内存视图memoryview
- numpy和scipy
- 双向队列和其它形式的队列
- python中列表可以当作栈或者队列使用
- collections.deque双端队列
- queue
- multiprocessing
- asyncio
- heapq
数组
这里是指python标准库中的数组,即array.array,而非numpy数组。
-
如果想要一个只包含数字的列表,那么数组更合适。数组支持所有跟可变序列相关的操作,包括.pop、.insert、.extend。
-
数组提供从文件读取和存入文件的方法,即.frombytes和.tofile。
-
创建时狐族需要使用类型码,该类型码用来表示再底层的C语言应该存放怎样的数据类型。比如array('b'),类型码为'b',此时创建的数组只能存放一个字节大小的整数。因为'b'代表有符号的字符,大小范围为-128到127。
-
创建包含1000万个浮点数的数组,并保存到文件,从文件中加载。如下边例子。将浮点数写入读出二进制文件都要比文本文件快很多倍,且二进制文件大小更小。
from array import array from random import random floats = array('d', (random() for i in range(10**2))) # 生成器表达式可以用于生成任意序列类型,'d'表示是双精度浮点数对象,跟python内置类型不同,array.array是需要指定数值精度的 print(floats[-1]) # 查看数组中最后一个元素 fp = open('floats.bin', 'wb') # 以二进制可写的方式打开一个文件,如果文件不存在,则创建该文件 floats.tofile(fp) # 用.tofile方法把数组中的内容写入到二进制文件floats.bin中 fp.close() # 关闭文件 floats2 = array('d') # 再创建一个存储双精度浮点数的数组对象 fp = open('floats.bin', 'rb') # 打开上边关闭的文件 floats2.fromfile(fp, 10**2) # 用.fromfile方法从打开的文件中读取10**2个元素到新建的数组 fp.close() # 关闭文件 print(floats2[-1]) # 查看第二个数组的最后一个元素 print(floats2 == floats) # 判断两个数组是否相等
-
除了array.array的tofile和fromfile方法外,pickle模块的dump方法也可以将对象存储到文件(也叫序列化),或者load方法从文件加载到对象(也叫反序列化)。pickle是python专用,文件后缀为.pkl。可以选择保存成文本文件或二进制文件。
-
python数组array.array非常类似C语言中的数组,要提供数据类型。
-
array数组不支持list.sort这种原地排序方法,要先用sorted生成一个排序好的新数组,然后让原数组名关联到此新数组。
a = array.array(a.typecode, sorted(a))
内存视图memoryview
memoryview是一个内置类,跟torch中的view方法有类似之处,就是从不同角度看待同一块内存区域的数据。
from array import array
from random import random
numbers = array('h', [i for i in range(-2, 3)]) # 列表推导式生成数组,数组元素是十六进制整数
memv = memoryview(numbers) # 从内存角度看待该数组
print(len(memv), memv.tolist()) # 打印出数组长度于具体值,可以看出跟number一样
print(memv[0]) # 数组的第一个元素就是现在内存视图的第一个元素
memv_oct = memv.cast('B') # memv.cast类型强制转换,改成以无符号字符的角度来看待numbers数组的那一块内存
print(len(memv_oct), memv_oct.tolist()) # 因为一个无符号字符占八个字节,原先十六进制中的一个数字被拆分成了两个,因此内存视图长度加倍
memv_oct[5] = 4 # 改变内存视图的某个索引的值,可以影响到原数组,因为是共享内存的。
print(numbers)
numpy和scipy
- numpy实现了多维同质数组和矩阵,scipy是基于numpy的库。
- numpy也可以轻易实现数组对象与文件的交互。numpy.save()用于将一个多维数组保存到一个二进制文件中。
双向队列和其它形式的队列
python中列表可以当作栈或者队列使用
- 当作队列使用时,.append()插入元素,.pop(0)删除元素,模拟先进先出
- 当作栈使用时,.append()插入元素,.pop(l.size()-1)删除元素,模拟后进先出。
- 缺点是删除列表第一个元素之类的操作会移动列表中所有元素,非常耗时。
collections.deque双端队列
collections.deque是一个线程安全的双端队列。
使用格式为:
from collections import deque
dp = deque(range(10), maxlen=10)
dp.rotate(3)
dp.rotate(-4)
dp.appendleft(-1)
dp.extend([11, 22, 33])
dp.extendleft([44, 55, 66])
- 构造双端队列时有一个可选参数maxlen,代表这个队列可以容纳的元素数量,一旦设定不可更改。如果添加元素超过容量,则会自动删除一部分元素,左边插入则右边删除,右边插入则左边删除。
queue
提供了线程安全类Queue、LifoQueue和PriorityQueue。
multiprocessing
这个包实现了自己的Queue,与queue.Queue类似,是设计给进程间通信用的。还有一个专门的multiprocessing.JoinableQueue类型。
asyncio
python3.4新提供的包,有Queue,LifoQueue,PriorityQueue,JoinableQueue,为异步管理提供了专门的便利。
heapq
没有队列类,但是提供了heappush和heappop方法,可以把可变序列当队列或优先队列用。