3.4. array — 序列化的固定类型结构
目的:有效的管理序列化的固定类型结构的数值型数据。
array
模块定义了一个与 list
非常相似的序列化数据结构,只是所有的成员都必须是相同的初始类型。支持的类型有:所有的数值型或者其他固定大小的初始类型,如 bytes 型。
对一些支持的类型可以参考以下表格。array
标准库的文档包含了完整的类型代码清单。
数组成员的类型代码
代码 | 类型 | 最小占用空间 (bytes) |
---|---|---|
b |
int | 1 |
B |
int | 1 |
h |
signed short | 2 |
H |
unsigned short | 2 |
i |
signed int | 2 |
I |
unsigned int | 2 |
l |
signed long | 4 |
L |
unsigned long | 4 |
q |
signed long long | 8 |
Q |
unsigned long long | 8 |
f |
float | 4 |
d |
double float | 8 |
初始化
array
实例化时会用到一个参数,该参数描述允许的数据类型。并且在初始化时可能还要给数组赋一个初值。
array_string.py
import array
import binascii
s = b'This is the array.'
a = array.array('b', s)
print('As byte string:', s)
print('As array :', a)
print('As hex :', binascii.hexlify(a))
在本例中,数组被配置为保存一个字节序列,并使用一个简单的字节字符串进行初始化。
$ python3 array_string.py
As byte string: b'This is the array.'
As array : array('b', [84, 104, 105, 115, 32, 105, 115, 32,
116, 104, 101, 32, 97, 114, 114, 97, 121, 46])
As hex : b'54686973206973207468652061727261792e'
操作数组
其它 Python 序列可以执行的操作, array
都可以用相同的方式执行,包括扩展数组的操作。
array_sequence.py
import array
import pprint
a = array.array('i', range(3))
print('Initial :', a)
a.extend(range(3))
print('Extended:', a)
print('Slice :', a[2:5])
print('Iterator:')
print(list(enumerate(a)))
支持的操作包括切片、迭代和向末尾添加元素。
$ python3 array_sequence.py
Initial : array('i', [0, 1, 2])
Extended: array('i', [0, 1, 2, 0, 1, 2])
Slice : array('i', [2, 0, 1])
Iterator:
[(0, 0), (1, 1), (2, 2), (3, 0), (4, 1), (5, 2)]
数组和文件
使用高效编码的内置方法,可以将数组的内容写入文件,也可以将文件的内容读取到数组中。
array_file.py
import array
import binascii
import tempfile
a = array.array('i', range(5))
print('A1:', a)
# 将数字数组写入临时文件
output = tempfile.NamedTemporaryFile()
a.tofile(output.file) # 必须传递一个 *真正的* 文件
output.flush()
# 读取原始数据
with open(output.name, 'rb') as input:
raw_data = input.read()
print('Raw Contents:', binascii.hexlify(raw_data))
# 将数据读取到一个数组中
input.seek(0)
a2 = array.array('i')
a2.fromfile(input, len(a))
print('A2:', a2)
这个例子演示了如何直接从一个二进制文件中读取数据「 raw, 」,而不是将其读入一个新的数组并将字节转换为适当的类型。
$ python3 array_file.py
A1: array('i', [0, 1, 2, 3, 4])
Raw Contents: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])
tofile()
使用 tobytes()
来格式化数据, fromfile()
使用 frombytes()
来将数据转换会数组实例。
array_tobytes.py
import array
import binascii
a = array.array('i', range(5))
print('A1:', a)
as_bytes = a.tobytes()
print('Bytes:', binascii.hexlify(as_bytes))
a2 = array.array('i')
a2.frombytes(as_bytes)
print('A2:', a2)
tobytes()
和 frombytes()
处理的都是字节字符串,而不是 Unicode 字符串。
$ python3 array_tobytes.py
A1: array('i', [0, 1, 2, 3, 4])
Bytes: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])
可供选择的字节顺序
如果数组中的数据不是按照本机字节顺序排列的,或者说如果在以不同的字节顺序(或通过网络)将数据发送给系统之前需要交换数据的位置,则可以在不迭代 Python 元素的情况之下转换整个数组的排列顺序。
array_byteswap.py
import array
import binascii
def to_hex(a):
chars_per_item = a.itemsize * 2 # 2 个16进制数字
hex_version = binascii.hexlify(a)
num_chunks = len(hex_version) // chars_per_item
for i in range(num_chunks):
start = i * chars_per_item
end = start + chars_per_item
yield hex_version[start:end]
start = int('0x12345678', 16)
end = start + 5
a1 = array.array('i', range(start, end))
a2 = array.array('i', range(start, end))
a2.byteswap()
fmt = '{:>12} {:>12} {:>12} {:>12}'
print(fmt.format('A1 hex', 'A1', 'A2 hex', 'A2'))
print(fmt.format('-' * 12, '-' * 12, '-' * 12, '-' * 12))
fmt = '{!r:>12} {:12} {!r:>12} {:12}'
for values in zip(to_hex(a1), a1, to_hex(a2), a2):
print(fmt.format(*values))
byteswap()
方法可以在 C语言 中切换数组中项的字节顺序,因此它比在 Python 中对数据进行循环要高效得多。
$ python3 array_byteswap.py
A1 hex A1 A2 hex A2
------------ ------------ ------------ ------------
b'78563412' 305419896 b'12345678' 2018915346
b'79563412' 305419897 b'12345679' 2035692562
b'7a563412' 305419898 b'1234567a' 2052469778
b'7b563412' 305419899 b'1234567b' 2069246994
b'7c563412' 305419900 b'1234567c' 2086024210
另请参阅
- 数组的标准库文档
struct
--struct
模块。- Numerical Python -- NumPy 是一个高效处理大数据集的 Python 库。
- Python 2 到 3 关于 array 的移植注释
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。