数组并不是Python内置的数据类型,是标准库array模块里面的。

虽然列表既灵活又简单,但面对各类需求时,我们可能会有更好的选择。比如,要存放 1000 万个浮点数的话,数组(array)的效率要高得多,因为数组在背后存的并不是 float 对象,而是数字的机器翻译,也就是字节表述。这一点就跟 C 语言中的数组一样。再比如说,如果需要频繁对序列做先进先出的操作,deque(双端队列)的速度应该会更快。如果在你的代码里,包含操作(比如检查一个元素是否出现在一个集合中)的频率很高,用 set(集合)会更合适。set专为检查元素是否存在做过优化但是它并不是序列,因为 set 是无序的

如果我们需要一个只包含数字的列表,那么 array.array 比 list 更高效。数组支持所有跟可变序列有关的操作,包括 .pop、.insert 和 .extend。另外,数组还提供从文件读取和存入文件的更快的方法,如 .frombytes 和 .tofile。

Python数组array的类型:

Type Code C Type Minimum size in bytes
‘c’ character 1
‘b’ signed integer 1
‘B’ unsigned integer 1
‘u’ Unicode character 2
‘h’ signed integer 2
‘H’ unsigned integer 2
‘i’ signed integer 2
‘I’ unsigned integer 2
‘l’ signed integer 4
‘L’ unsigned integer 4
‘f’ floating point 4
‘d’ floating point 8

更多请参考这里

Python 数组跟 C 语言数组一样精简。创建数组需要一个类型码,这个类型码用来表示在底层的 C 语言应该存放怎样的数据类型。比如 b 类型码代表的是有符号的字符(signed char),因此 array(‘b’) 创建出的数组就只能存放一个字节大小的整数,范围从 -128 到 127,这样在序列很大的时候,我们能节省很多空间。而且Python不会允许你在数组里存放除指定类型之外的数据

展示了从创建一个有 1000 万个随机浮点数的数组开始,到如何把这个数组存放到文件里,再到如何从文件读取这个数组示例:

>>> from array import array 
>>> from random import random
>>> floats = array('d', (random() for i in range(10**7))) 
>>> floats[-1] 
0.07802343889111107 
>>> fp = open('floats.bin', 'wb') 
>>> floats.tofile(fp)  
>>> fp.close() 
>>> floats2 = array('d') 
>>> fp = open('floats.bin', 'rb') 
>>> floats2.fromfile(fp, 10**7) 
>>> fp.close() 
>>> floats2[-1] 
0.07802343889111107 
>>> floats2 == floats 
True

利用一个可迭代对象来建立一个双精度浮点数组(类型码是 ’d’),这里我们用的可迭代对象是一个生成器表达式。

二进制文件与文本文件的读取差别很大!

从上面的代码我们能得出结论,array.tofile 和 array.fromfile 用起来很简单。把这段代码跑一跑,你还会发现它的速度也很快。一个小试验告诉我,用 array.fromfile 从一个二进制文件里读出 1000 万个双精度浮点数只需要 0.1 秒,这比从文本文件里读取的速度要快 60 倍,因为后者会使用内置的 float 方法把每一行文字转换成浮点数。

另外,使用 array.tofile 写入到二进制文件,比以每行一个浮点数的方式把所有数字写入到文本文件要快 7 倍。另外,1000 万个这样的数在二进制文件里只占用 80 000 000 个字节(每个浮点数占用 8 个字节, 不需要任何额外空间),如果是文本文件的话,我们需要 181 515 739 个字节。

另外一个快速序列化数字类型的方法是使用pickle模块。pickle.dump 处理浮点数组的速度几乎跟 array.tofile 一样快。不过前者可以处理几乎所有的内置数字类型,包含复数、嵌套集合,甚至用户自定义的类。前提是这些类没有什么特别复杂的实现

从 Python 3.4 开始,数组类型不再支持诸如 list.sort() 这种就地排序方法。要给数组排序的话,得用 sorted 函数新建一个数组:

a = array.array(a.typecode, sorted(a))

想要在不打乱次序的情况下为数组添加新的元素,bisect.insort 还是能派上用场。

整理自《流畅的Python》关于array模块的内容。