array和list一样,属于序列数据类型,但是它只能存储字符(character)、整数(integer)、浮点数(float)这些基本数据类型。数组( array )的效率要高得多,因为数组在背后存的是字节。
memoryview 是一个内置类,它能让用户在不复制内容的情况下操作同一个数组的不同切片。
bytes 或 bytearray 对象的各个元素是介于 0~255(含)之间的整数。
struct 模块提供了一些函数,把打包的字节序列转换成不同类型字段组成的元组,还有一些函数用于执行反向转换,把元组转换成打包的字节序列。 struct 模块能处理 bytes 、bytearray 和 memoryview 对象。
下面通过《流畅的Pyhon》示例,看看这几种类型怎么相互转换:
示例2-21 通过改变数组中的一个字节来更新数组里某个元素的值
# 含有 5 个短整型有符号整数的数组(类型码是 'h' )
>>> numbers = array.array('h', [-2, -1, 0, 1, 2])
# 创建一个 memoryview
>>> memv = memoryview(numbers)
numbers为有符号整数,占用内存空间大小为2字节,以大端模式在内存中表示为(书中是小端模式):
有符号整数 | -2 | -1 | 0 | 1 | 2 |
---|---|---|---|---|---|
16进制表示 |
0xff 0xfe |
0xff 0xff |
0x00 0x00 |
0x00 0x01 |
0x00 0x02 |
2进制表示 |
0b11111111 0b11111110 |
0b11111111 0b11111111 |
0b00000000 0b00000000 |
0b00000000 0b00000001 |
0b00000000 0b00000010 |
在内存中共占用10字节大小,拼接在一起表示即为:
0b11111111 11111110 11111111 11111111 00000000 00000000 00000000 00000001 00000000 00000010
16进制表示的转换代码:
方法一:
>>> (-2).to_bytes(2, byteorder='big',signed=True)
b'\xff\xfe'
>>> (-1).to_bytes(2, byteorder='big',signed=True)
b'\xff\xff'
>>> (0).to_bytes(2, byteorder='big',signed=True)
b'\x00\x00'
>>> (1).to_bytes(2, byteorder='big',signed=True)
b'\x00\x01'
>>> (2).to_bytes(2, byteorder='big',signed=True)
b'\x00\x02'
方法二:
>>> numbers = array.array('h', [-2, -1, 0, 1, 2])
>>> octets = bytes(numbers)
>>> octets
b'\xfe\xff\xff\xff\x00\x00\x01\x00\x02\x00'
方法三:
>>> import struct
>>> struct.pack("<hhhhh", -2,-1,0,1,2)
b'\xfe\xff\xff\xff\x00\x00\x01\x00\x02\x00'
>>> struct.unpack("<hhhhh", octets)
(-2, -1, 0, 1, 2)
16进制转换为2进制:
>>> bin(int("ff", 16))
'0b11111111'
>>> bin(int("fe", 16))
'0b11111110'
通过memoryview模块的cast,把 memv 里的内容转换成 'B' 类型,也就是无符号字符:
>>> memv_oct = memv.cast('B')
>>> memv_oct.tolist()
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
'B'类型占用1个字节内存空间,按1字节读取(书中为以小端模式表示):
255 254 255 255 0 0 0 1 0 2
也可以使用struct的unpack
>>> struct.unpack("<BBBBBBBBBB", memv_oct)
(254, 255, 255, 255, 0, 0, 1, 0, 2, 0)
以上是基本类型与二进制数据的转换。
对于字符类型,可以使用strings的encode方法进行编码,bytes方法也支持将字符串编码为二进制格式。
对于其它复杂对象,则可以使用pickle模块。