Python/字节数组

Buffer Protocol是特定的Python对象,包装了访问内存数组或者缓冲区。包括内置类型:

  • bytes是只读字节数组。
  • bytearray是可读写字节数组。
  • array.array
a=b"abc"  #创建bytes对象
bytes("汉字","utf-8") #创建bytes对象,解码方式为utf-8
b=bytearray(b"abc") #创建bytearray对象

与字符串一样,支持append、extend、upper等方法,加法、乘法等运算。

bytes 编辑

class bytes([source[, encoding[, errors]]])构造函数,如

a=b'still allows embedded "double" quotes'

其他构造函数:

bytes(10)
bytes(range(20))
bytes(otherBytesObj)

类方法:

  • fromhex(string):以16进制解码一个字符串,其中的空白符被忽略。如bytes.fromhex('2Ef0 F1f2 ')
  • hex([sep[, bytes_per_sep]]):把内容编码为16进制数字组成的字符串。bytes_per_sep控制分隔符出现在哪个字节,正值从右数,负值从左数

bytearray 编辑

bytearray是可变的(mutable)版本,与只读的bytes对应。

构造函数:

bytearray()
bytearray(10)
bytearray(range(20))
bytearray(b'Hi!')

有类似的类方法fromhex和hex

bytes和bytearray共同的一些类方法 编辑

  • count(sub[, start[, end]]):返回不重叠的子串sub的出现次数
  • removeprefix(prefix, /):去除跟定的前缀子串
  • removesuffix(suffix, /)
  • decode(encoding='utf-8', errors='strict'):返回从给定字节解码的字符串
  • endswith(suffix[, start[, end]])
  • find(sub[, start[, end]]):返回子串sub最小出现的下标值。未找到返回-1
  • index(sub[, start[, end]]):类似find方法,但未找到抛出异常
  • join(iterable):返回一个新的对象
  • maketrans(from, to):这个静态方法返回一个可用于 bytes.translate() 的转换表,它将把 from 中的每个字符映射到 to 中相同位置的字符; from 和 to 必须都是类似字节对象(bytes-like objects)并且具有相同的长度。
  • partition(sep):在第一次出现 sep 时拆分序列,并返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之后的部分。 如果未找到分隔符,则返回一个包含原始序列副本的 3 元组,后跟两个空字节或 bytearray 对象。
  • replace(old, new[, count]):如果给出参数count,只对前面count次替换。
  • rfind(sub[, start[, end]])
  • rindex(sub[, start[, end]])
  • rpartition(sep)
  • startswith(prefix[, start[, end]])
  • translate(table, /, delete=b):返回新对象——删除了参数 delete 中出现的所有字节,其余字节通过给定的转换表映射,该转换表必须是长度为 256 的字节对象。可以使用 bytes.maketrans() 方法创建转换表。对于只删除字符的翻译,将 table 参数设置为 None。
  • ljust(width[, fillbyte]):返回新对象,在左侧填充字符,如果原对象字节长度小于width
  • lstrip([chars]):默认从左侧开头位置删除空白符。该函数删除参数chars中所有字符的任意组合;而removeprefix方法只删除子串。
  • rjust(width[, fillbyte])
  • rsplit(sep=None, maxsplit=- 1)
  • rstrip([chars])
  • split(sep=None, maxsplit=- 1)
  • strip([chars])
  • capitalize()
  • expandtabs(tabsize=8):返回序列的副本,其中所有制表符被指定个数的空格符替换
  • isalnum()
  • isalpha()
  • isascii()
  • isdigit()
  • islower()
  • isspace()
  • istitle()
  • isupper()
  • lower()
  • splitlines(keepends=False):返回一个list
  • swapcase()
  • title()
  • upper()
  • zfill(width):左侧零填充

print(格式化参数),转换说明符包含两个或多个字符并具有以下组件,这些组件必须按此顺序出现:

  1. '%' 字符,标记说明符的开始。
  2. 映射键(可选),由带括号的字符序列组成,为后续字典变量中的key
  3. 转换标志(conversion flag,可选),影响某些转换类型的结果。'#'值转换使用“alternate form”;'0'表示零填充数值;'-'表示左对齐;' '产生有符号转换;'+'产生带正负号的转换。
  4. 最小字段宽度(可选)。如果指定为“*”(星号),则从值中元组的下一个元素读取实际宽度,并且要转换的对象位于最小字段宽度和可选精度之后。
  5. 精度(可选),以“.”形式给出(点)后跟精度。如果指定为 '*'(星号),则从 values 中元组的下一个元素读取实际精度,并且要转换的值位于精度之后。
  6. 长度修饰符(可选),可为h, l, L。但Python忽略它们。
  7. 转换类型。基本类似C语言的sprintf函数。's' 或'b' 表示字节(任何遵循缓冲区协议或具有 __bytes__() 的对象)。'r' 或'a' 表示字节(使用 repr(obj).encode('ascii', 'backslashreplace') 转换任何 Python 对象)。

例如:

 print(b'%(language)s has %(number)03d quote types.' %{b'language': b"Python", b"number": 2})

array.array 编辑

如果需要使用数组,需要如下:

import array
a = array.array('h', [0, 1, 2, 3])

构造函数class array.array(typecode[, initializer])创建一个由 typecode限制类型的新数组,并由initializer的值进行初始化。实际上,会根据initializer的情况调用本类的fromlist()、 frombytes() 或 fromunicode() 方法将初始元素添加到数组中,或者将可迭代对象作为initializer传给 extend() 方法。

本类的方法或属性:

  • array.typecode:用于创建数组的类型码字符。
  • array.itemsize:在内部表示中一个数组项的字节长度。
  • array.append(x):添加一个值为 x 的新项到数组末尾。
  • array.buffer_info():返回一个元组 (address, length) 以给出用于存放数组内容的缓冲区元素的当前内存地址和长度。 以字节表示的内存缓冲区大小可通过 array.buffer_info()[1] * array.itemsize 来计算。
  • array.byteswap():对所有数组项做大小端序交换。 此方法只支持大小为 1, 2, 4 或 8 字节的值;对于其他值类型将引发 RuntimeError。 它适用于从不同字节序机器所生成的文件中读取数据的情况。
  • array.count(x):返回 x 在数组中的出现次数。
  • array.extend(iterable):将来自 iterable 的项添加到数组末尾。 如果 iterable 是另一个数组,它必须具有 完全 相同的类型码;否则将引发 TypeError。 如果 iterable 不是一个数组,则它必须为可迭代对象并且其元素必须为可添加到数组的适当类型。
  • array.frombytes(s):添加来自字节串的项,将字符节解读为机器值的数组(相当于使用 fromfile() 方法从文件中读取数据)。
  • array.fromfile(f, n):从 file object f 中读取 n 项并将它们添加到数组末尾。 如果可用数据少于 n 项,则会引发 EOFError,但可用的项仍然会被插入数组。
  • array.fromlist(list):添加来自 list 的项。 这等价于 for x in list: a.append(x),区别在于如果发生类型错误,数组将不会被改变。
  • array.fromunicode(s):使用来自给定 Unicode 字符串的数组扩展数组。 数组必须是类型为 'u' 的数组;否则将引发 ValueError。 请使用 array.frombytes(unicodestring.encode(enc)) 来将 Unicode 数据添加到其他类型的数组。
  • array.index(x[, start[, stop]]):返回最小的 i 使得 i 为数组中首次出现的 x 的索引号。 指定可选参数 start 和 stop 以便在数组的一个子部分内部搜索 x。 如果未找到 x 则会引发 ValueError。
  • array.insert(i, x):将值 x 作为新项插入数组的 i 位置之前。 负值将被视为相对于数组末尾的位置。
  • array.pop([i]):从数组中移除序号为 i 的项并将其返回。 可选参数值默认为 -1,因此默认将移除并返回末尾项。
  • array.remove(x):从数组中移除首次出现的 x。
  • array.reverse():反转数组中各项的顺序。
  • array.tobytes():将数组转换为一个机器值数组并返回其字节表示(即相当与通过 tofile() 方法写入到文件的字节序列。)
  • array.tofile(f):将所有项(作为机器值)写入到 file object f。
  • array.tolist():将数组转换为包含相同项的普通列表。
  • array.tounicode():将数组转换为一个 Unicode 字符串。 数组必须是类型为 'u' 的数组;否则将引发 ValueError。 请使用 array.tobytes().decode(enc) 来从其他类型的数组生成 Unicode 字符串。

memoryview 编辑

memoryview对象支持访问一个满足缓冲区协议(buffer protocol)的对象的内部数据而无需复制操作。这包括bytes、bytearray、array.array等类型。如:

a=bytearray([0x10,0x11,0x12,0x13,0x14,0x15,0x16])
v=memoryview(a)

内存视图转化为其它类型,可用tobytes、tolist,或者cast方法,或者struct.unpack方法。

len(view)等于tolist的长度

view.ndim = 0则长度为1。view.ndim = 1则长度为view中元素个数。

itemsize特性给出单个元素的字节数。

调用内存视图的release函数,可以使得原对象实例恢复全部操作能力。

memoryview支持切片和索引操作。

memoryview可修改内容。如:

data = bytearray(b'abcefg')
v = memoryview(data)
v[1:4] = b'123' #data内容变为 bytearray(b'z123fg')

memoryview是按维度和元素值比较相等,如

a = array.array('I', [1, 2, 3, 4, 5])
b = array.array('d', [1.0, 2.0, 3.0, 4.0, 5.0])
c = array.array('b', [5, 3, 1])
x = memoryview(a)
y = memoryview(b)
x == a == y == b # 为True

其它方法有:

  • tobytes(order=None):参数值可以为{‘C’, ‘F’, ‘A’}分别表示C语言、Fortran语言、物理序。
  • hex([sep[, bytes_per_sep]]):返回十六进制表示的字符串。
  • tolist()
  • toreadonly():返回只读的memoryview
  • release():释放基础数据。当前memoryview不再有效。
  • cast(format[, shape]):创建一个新的memoryview,但基础buffer数据不变。如:
import struct
buf = struct.pack("i"*12, *list(range(12)))
x = memoryview(buf)
y = x.cast('i', shape=[2,2,3])
y.tolist() #结果为[[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]

memoryview的只读属性:

  • obj:返回基础buffer的对象
  • nbytes:总字节数
  • readonly:是否只读
  • format
  • itemsize
  • ndim:多维数组的维数
  • shape:多维数组的维度的元组表示
  • strides:多维数组各维度的字节步长
  • c_contiguous
  • f_contiguous
  • contiguous

格式说明 编辑

格式类型的前缀
字符 字节序 尺寸 对齐
@ native native native
= native standard none
< 小尾序 standard none
> 大尾序 standard none
! 网络序 standard none
格式类型
Format C Type Python type Standard size 注释
x pad byte no value
c char bytes of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1 C99引入的类型。返回值是 True或False
h short integer 2
H short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
n ssize_t integer
N size_t integer
e 半精度 float 2
f float float 4
d double float 8
s char[] bytes 整数后跟s,表示字节序列长度。默认为1。会自动截断或补0字节
p char[] bytes Pascal string
P void * integer

数字后面跟随格式字符,表示该格式字符重复的次数。例如:'4h'等价于'hhhh'