用途:高效管理固定类型的数值数据序列。
array 模块定义了一种序列数据结构,其外观与列表(list)非常相似,不同之处在于:该结构中所有元素必须是相同的基本类型(primitive type)。支持的类型包括所有数值类型或其他固定大小的基本类型(如字节类型 bytes)。
数组元素的类型码(Type Codes for array Members)
下表列出了部分支持的类型,array 模块的标准库文档中提供了完整的类型码列表。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
初始化(Initialization)
实例化数组时,需传入一个参数指定允许存储的数据类型,还可选择性传入初始数据序列以存储到数组中。
示例代码:array_string.py
import array
import binascii
s = b'This is the array.' # 定义字节字符串
a = array.array('b', s) # 初始化数组:类型码 'b'(字节),初始数据为 s
print('作为字节字符串:', s)
print('作为数组 :', a)
print('作为十六进制 :', binascii.hexlify(a))
在该示例中,数组被配置为存储字节序列,并使用简单的字节字符串进行初始化。
运行结果
$ python3 array_string.py
作为字节字符串: b'This is the array.'
作为数组 : array('b', [84, 104, 105, 115, 32, 105, 115, 32, 116, 104, 101, 32, 97, 114, 114, 97, 121, 46])
作为十六进制 : b'54686973206973207468652061727261792e'
操作数组(Manipulating Arrays)
数组可通过与其他 Python 序列相同的方式进行扩展或其他操作。
示例代码:array_sequence.py
import array
import pprint
a = array.array('i', range(3)) # 初始化数组:类型码 'i'(有符号整数),初始数据为 0、1、2
print('初始状态 :', a)
a.extend(range(3)) # 扩展数组:添加 0、1、2
print('扩展后 :', a)
print('切片结果 :', a[2:5]) # 切片操作:获取索引 2 到 4 的元素
print('迭代器 :')
print(list(enumerate(a))) # 枚举数组元素(索引+值)
支持的操作包括切片、迭代和向末尾添加元素等。
运行结果
$ python3 array_sequence.py
初始状态 : array('i', [0, 1, 2])
扩展后 : array('i', [0, 1, 2, 0, 1, 2])
切片结果 : array('i', [2, 0, 1])
迭代器 :
[(0, 0), (1, 1), (2, 2), (3, 0), (4, 1), (5, 2)]
数组与文件(Arrays and Files)
数组的内容可通过内置方法写入文件或从文件读取,这些方法为该用途进行了高效的代码实现。
示例代码:array_file.py
import array
import binascii
import tempfile
a = array.array('i', range(5)) # 初始化数组:数据为 0、1、2、3、4
print('A1:', a)
# 将数组写入临时文件
output = tempfile.NamedTemporaryFile()
a.tofile(output.file) # 必须传入一个“实际的文件对象”
output.flush() # 刷新缓冲区,确保数据写入文件
# 读取文件中的原始数据
with open(output.name, 'rb') as input:
raw_data = input.read() # 读取原始二进制数据
print('原始内容:', binascii.hexlify(raw_data))
# 将数据读入新数组
input.seek(0) # 移动文件指针到开头
a2 = array.array('i') # 初始化空数组(类型与原数组一致)
a2.fromfile(input, len(a)) # 从文件读取指定长度的数据
print('A2:', a2)
该示例对比了两种读取方式:一是“原始读取”(直接从二进制文件读取数据),二是将数据读入新数组并将字节转换为相应类型。
运行结果
$ python3 array_file.py
A1: array('i', [0, 1, 2, 3, 4])
原始内容: 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('字节序列:', binascii.hexlify(as_bytes))
a2 = array.array('i') # 初始化空数组
a2.frombytes(as_bytes) # 从字节字符串恢复数组
print('A2:', a2)
注意:tobytes() 和 frombytes() 均作用于字节字符串(byte string),而非 Unicode 字符串。
运行结果
$ python3 array_tobytes.py
A1: array('i', [0, 1, 2, 3, 4])
字节序列: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])
字节序转换(Alternative Byte Ordering)
若数组中的数据不是本机字节序,或数据在发送到字节序不同的系统(或通过网络发送)前需要交换字节序,可直接转换整个数组,无需在 Python 中遍历元素。
示例代码:array_byteswap.py
import array
import binascii
def to_hex(a):
"""将数组转换为十六进制字符串的生成器"""
chars_per_item = a.itemsize * 2# 每个元素对应 2 个十六进制字符
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) # 十六进制转十进制:305419896
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 十六进制', 'A1 数值', 'A2 十六进制', '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 十六进制 A1 数值 A2 十六进制 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

