• Python二进制序列类型(二)array、struct和memoryview


    Python实用教程_spiritx的博客-CSDN博客

    前面一篇学习了bytes和bytearray,这一篇学习其他的两个类型array和memoryview,同时会对struct模块和 codecs进行学习

    array

    高效的数字数组

    此模块定义了一种对象类型,可以紧凑地表示由基本值(字符、整数、浮点数)组成的数组。数组是序列类型,其行为与列表非常相似,不同之处在于其中存储的对象类型是受限的,在数组对象创建时用单个字符的 类型码 来指定。已定义的类型码如下:

    类型码

    C 类型

    Python 类型

    以字节为单位的最小大小

    备注

    'b'

    signed char

    int

    1

    'B'

    unsigned char

    int

    1

    'u'

    wchar_t

    Unicode 字符

    2

    (1)

    'h'

    signed short

    int

    2

    'H'

    unsigned short

    int

    2

    'i'

    signed int

    int

    2

    'I'

    unsigned int

    int

    2

    'l'

    signed long

    int

    4

    'L'

    unsigned long

    int

    4

    'q'

    signed long long

    int

    8

    'Q'

    unsigned long long

    int

    8

    'f'

    float

    float

    4

    'd'

    double

    float

    8

    注释:

    (1)在不同的平台上,它可能为 16 位或 32 位。

    在 3.9 版更改: array('u') 现在使用 wchar_t 作为 C 类型而不是已不建议使用的 Py_UNICODE。这个改变不会影响其行为,因为 Py_UNICODE 自 Python 3.3 起就是 wchar_t 的别名。从 3.3 版起不建议使用,将在 4.0 版中移除。值的实际表示是由机器架构(严格说是由 C 实现)决定的。实际大小可以通过 array.itemsize 属性来访问。

    array.typecodes中定义了所有的类型码

    1. >>> import array
    2. >>> array.typecodes
    3. 'bBuhHiIlLqQfd'

    数组的定义

    语法:

    class array.array(typecode[, initializer])

    一个由 typecode 限制类型的新数组,并通过可选的 initializer 进行初始化。initializer 必须为一个列表、bytes-like object 或在合适类型元素上迭代的可迭代对象。

    如果是一个列表或字符串,该 initializer 会被传给新数组的 fromlist(),frombytes() 或 fromunicode() 方法(见下)以将初始项添加到数组中。其它将可迭代对象将被传给 extend() 方法。

    数组对象支持普通的序列操作如索引、切片、拼接和重复等。当使用切片赋值时,所赋的值必须为具有相同类型码的数组对象;所有其他情况都将引发 TypeError。数组对象也实现了缓冲区接口,可以用于所有支持 字节类对象 的场合。

    主要成员和方法

    类型码字符

    成员typecode

    在创建数组时指定的类型码字符。

    单个数组项的长度

    成员itemsize

    在内部表示中,单个数组项的长度,单位为字节。

    长度与字符类型密切相关,实际是typecode和系统类型决定了itemsize

    1. import array
    2. arr = array.array('i',[0,1,1,3]) #创建array数组
    3. print(arr) #array('i', [0, 1, 1, 3])
    4. print(arr.typecode) #i
    5. print(arr.itemsize) #4

    追加数组

    将字节串追加到数组

    array.frombytes(s)

    添加来自字节串的项,将字符节解读为机器值的数组(相当于使用 fromfile() 方法从文件中读取数据)。

    3.2 新版功能: fromstring() 被重命名为含义更准确的 frombytes()。

    这个方法要求比较苛刻,要求array和s的长度一致,并且s只能是字节类串

    1. import array
    2. arr = array.array('i',[0,1,2,3]) #创建array数组
    3. print(arr) #array('i', [0, 1, 2, 3])
    4. print(arr.itemsize) #4
    5. b1 = b'12'
    6. print(f"{len(b1)=}") #len(b1)=2
    7. #arr.frombytes(b1) #ValueError itemsize<>len(b1)
    8. b2 = b'1234'
    9. print(f"{len(b2)=}") #len(b2)=4
    10. arr.frombytes(b2)
    11. print(arr) #array('i', [0, 1, 2, 3, 875770417])
    12. b3 = bytes([1,2,3,4])
    13. print(f"{len(b3)=}")
    14. arr.frombytes(b3)
    15. print(arr) #array('i', [0, 1, 2, 3, 875770417, 67305985])
    从文件中追加到数组

    array.fromfile(f, n)

    从 file object f 中读取 n 项并将它们添加到数组末尾。 如果可用数据少于 n 项,则会引发 EOFError,但可用的项仍然会被插入数组。

    从序列中追加到数组

    array.fromlist(list)

    添加来自 list 的项。 这等价于 for x in list: a.append(x),区别在于如果发生类型错误,数组将不会被改变。

    1. arr = array.array('i',[0,1,2,3]) #创建array数组
    2. b4 = list([10,11])
    3. arr.fromlist(b4)
    4. print(arr) #array('i', [0, 1, 2, 3, 10, 11])
    5. b5 = list(['ab', 'cd'])
    6. #arr.fromlist(b5) #TypeError
    从Unicode字符串追加数组

    array.fromunicode(s)

    使用来自给定 Unicode 字符串的数组扩展数组。 数组必须是类型为 'u' 的数组;否则将引发 ValueError。 请使用 array.frombytes(unicodestring.encode(enc)) 来将 Unicode 数据添加到其他类型的数组。

    追加一个元素

    array.append(x)

    添加一个值为 x 的新项到数组末尾。

    从iter对象追加素组

    array.extend(iterable)

    将来自 iterable 的项添加到数组末尾。 如果 iterable 是另一个数组,它必须具有 完全 相同的类型码;否则将引发 TypeError。 如果 iterable 不是一个数组,则它必须为可迭代对象并且其元素必须为可添加到数组的适当类型。

    转换为其他对象

    转换为字节串

    array.tobytes()

    将数组转换为一个机器值数组并返回其字节表示(即相当与通过 tofile() 方法写入到文件的字节序列。)

    3.2 新版功能: tostring() 被重命名为含义更准确的 tobytes()。

    写入文件

    array.tofile(f)

    将所有项(作为机器值)写入到 file object f。

    转换为列表

    array.tolist()

    将数组转换为包含相同项的普通列表。

    转换为Unicode字符串

    array.tounicode()

    将数组转换为一个 Unicode 字符串。 数组必须是类型为 'u' 的数组;否则将引发 ValueError。 请使用 array.tobytes().decode(enc) 来从其他类型的数组生成 Unicode 字符串。

    当一个数组对象被打印或转换为字符串时,它会表示为 array(typecode, initializer)。 如果数组为空则 initializer 会被省略,否则如果 typecode 为 'u' 则它是一个字符串,否则它是一个数字列表。 使用 eval() 保证能将字符串转换回具有相同类型和值的数组,只要 array 类已通过 from array import array 被引入。 例如:

    1. >>> array.array('l')
    2. array('l')
    3. >>> array.array('u', 'hello \u2641')
    4. array('u', 'hello ♁')
    5. >>> array.array('l', [1,2,3,4,5,6])
    6. array('l', [1, 2, 3, 4, 5, 6])
    7. >>> array.array('d', [1.0,2.0,3.0,4.0,5.0,6.0])
    8. array('d', [1.0, 2.0, 3.0, 4.0, 5.0, 6.0])

    插入

    array.insert(i, x)

    将值 x 作为新项插入数组的 i 位置之前。 负值将被视为相对于数组末尾的位置。

    1. import array
    2. arr = array.array('i',[0,1,2,3]) #创建array数组
    3. print(arr) #array('i', [0, 1, 2, 3])
    4. print(arr.typecode) #i
    5. print(arr.itemsize) #4
    6. arr.append(100)
    7. print(arr) #array('i', [0, 1, 1, 3, 100])
    8. arr.insert(3,101)
    9. print(arr) #array('i', [0, 1, 2, 101, 3, 100])

    统计元素出现的次数

    array.count(x)

    返回 x 在数组中的出现次数。

    查找元素

    array.index(x[, start[, stop]])

    返回最小的 i 使得 i 为数组中首次出现的 x 的索引号。 指定可选参数 start 和 stop 以便在数组的一个子部分内部搜索 x。 如果未找到 x 则会引发 ValueError。

    在 3.10 版更改: 添加了可选的 start 和 stop 形参。

    移除尾部元素或指定位置

    sarray.pop([i])

    从数组中移除序号为 i 的项并将其返回。 可选参数值默认为 -1,因此默认将移除并返回末尾项。

    删除指定元素

    array.remove(x)

    从数组中移除首次出现的 x。

    反转顺序

    array.reverse()

    反转数组中各项的顺序。

    获取内存信息

    array.buffer_info()

    返回一个元组 (address, length) 给出存放数组内容的内存缓冲区的当前地址和长度(以元素个数为单位)。以字节为单位的的内存缓冲区大小可通过 array.buffer_info()[1] * array.itemsize 来计算。工作在需要内存地址的底层(因此天然地不够安全)的 I/O 接口上时,这有时会有用,例如某些 ioctl() 操作。只要数组还存在,并且没有对其应用过改变长度的操作,则返回的数值就是有效的。

    备注 当在 C 或 C++ 编写的代码中使用数组对象时(这是有效使用此类信息的唯一方式),使用数组对象所支持的缓冲区接口更为适宜。 此方法仅保留用作向下兼容,应避免在新代码中使用。 缓冲区接口的文档参见 缓冲协议。

    字节对调
    array.byteswap()

    “字节对调”所有数组项。 此方法只支持大小为 1, 2, 4 或 8 字节的值;对于其他值类型将引发 RuntimeError。 它适用于从不同字节序机器所生成的文件中读取数据的情况。

    struct

    字节串数据的打包或解包.

    格式串字符

    格式串字符描述了打包和拆包时的数据格式,格式字符指定数据类型,特殊字符控制字节顺序、大小端和对齐方式。

    字节顺序,大小和对齐方式

    格式字符串的第一个字符可用于指示打包数据的字节顺序,大小和对齐方式:

    字符

    字节顺序

    大小

    对齐方式

    @

    按原字节

    按原字节

    按原字节

    =

    按原字节

    标准

    <

    小端

    标准

    >

    大端

    标准

    !

    网络(=大端)

    标准

    如果第一个字符不是其中之一,则假定为 '@' 。

    本机大小和对齐方式是使用 C 编译器的 sizeof 表达式来确定的。 这总是会与本机字节顺序相绑定。

    请注意 '@' 和 '=' 之间的区别:两个都使用本机字节顺序,但后者的大小和对齐方式是标准化的。

    形式 '!' 代表网络字节顺序总是使用在 IETF RFC 1700 中所定义的大端序。

    没有什么方式能指定非本机字节顺序(强制字节对调);请正确选择使用 '<' 或 '>'

    注释:

    • 填充只会在连续结构成员之间自动添加。 填充不会添加到已编码结构的开头和末尾。
    • 当使用非本机大小和对齐方式即 '<', '>', '=', and '!' 时不会添加任何填充。
    • 要将结构的末尾对齐到符合特定类型的对齐要求,请以该类型代码加重复计数的零作为格式结束。

    格式字符

    格式字符具有以下含义;C 和 Python 值之间的按其指定类型的转换应当是相当明显的。 ‘标准大小’列是指当使用标准大小时以字节表示的已打包值大小;也就是当格式字符串以 '<''>''!' 或 '=' 之一开头的情况。 当使用本机大小时,已打包值的大小取决于具体的平台。

    格式

    C 类型

    Python 类型

    标准大小

    备注

    x

    填充字节

    (7)

    c

    char

    长度为 1 的字节串

    1

    b

    signed char

    整数

    1

    (1), (2)

    B

    unsigned char

    整数

    1

    (2)

    ?

    _Bool

    bool

    1

    (1)

    h

    short

    整数

    2

    (2)

    H

    unsigned short

    整数

    2

    (2)

    i

    int

    整数

    4

    (2)

    I

    unsigned int

    整数

    4

    (2)

    l

    long

    整数

    4

    (2)

    L

    unsigned long

    整数

    4

    (2)

    q

    long long

    整数

    8

    (2)

    Q

    unsigned long long

    整数

    8

    (2)

    n

    ssize_t

    整数

    (3)

    N

    size_t

    整数

    (3)

    e

    (6)

    float

    2

    (4)

    f

    float

    float

    4

    (4)

    d

    double

    float

    8

    (4)

    s

    char[]

    字节串

    (9)

    p

    char[]

    字节串

    (8)

    P

    void*

    整数

    (5)

    注释:

    (1)“?”转换代码对应于C99定义的_Bool类型。如果此类型不可用,则使用char对其进行模拟。在标准模式中,它总是由一个字节表示。

    (2)当尝试使用任何整数转换代码打包非整数时,如果非整数有__index__()方法,则在打包前调用该方法将参数转换为整数。

    在 3.2 版更改: Added use of the __index__() method for non-integers.

    (3)'n' 和 'N' 转换码仅对本机大小可用(选择为默认或使用 '@' 字节顺序字符)。 对于标准大小,你可以使用适合你的应用的任何其他整数格式。

    (4)对于 'f', 'd' 和 'e' 转换码,打包表示形式将使用 IEEE 754 binary32, binary64 或 binary16 格式 (分别对应于 'f', 'd' 或 'e'),无论平台使用何种浮点格式。

    (5)'P' 格式字符仅对本机字节顺序可用(选择为默认或使用 '@' 字节顺序字符)。 字节顺序字符 '=' 选择使用基于主机系统的小端或大端排序。 struct 模块不会将其解读为本机排序,因此 'P' 格式将不可用。

    (6)IEEE 754 binary16 "半精度" 类型是在 IEEE 754 标准 的 2008 修订版中引入的。 它包含一个符号位,5 个指数位和 11 个精度位(明确存储 10 位),可以完全精确地表示大致范围在 6.1e-05 和 6.5e+04 之间的数字。 此类型并不被 C 编译器广泛支持:在一台典型的机器上,可以使用 unsigned short 进行存储,但不会被用于数学运算。 

    (7)当打包时,'x'将填充一个NULL字节.

    (8)'p' 格式字符用于编码“Pascal 字符串”,即存储在由计数指定的 固定长度字节 中的可变长度短字符串。 所存储的第一个字节为字符串长度或 255 中的较小值。 之后是字符串对应的字节。 如果传入 pack() 的字符串过长(超过计数值减 1),则只有字符串前 count-1 个字节会被存储。 如果字符串短于 count-1,则会填充空字节以使得恰好使用了 count 个字节。 请注意对于 unpack(),'p' 格式字符会消耗 count 个字节,但返回的字符串永远不会包含超过 255 个字节。

    (9)对于's'格式字符,计数被解释为字节的长度,而不是像其他格式字符那样的重复计数;例如,“10s”表示单个10字节字符串映射到单个Python字节字符串或从单个Python字节串映射,而“10c”表示10个单独的单字节字符元素(例如cccccccc)映射到10个不同的Python字节对象或从10个不同Python字节对象映射。如果未给定计数,则默认为1。对于打包,字符串会被适当地截断或填充空字节以使其适合。对于解包,生成的字节对象始终具有指定数量的字节。特殊情况下,“0s”表示单个空字符串(而“0c”表示0个字符)。

    格式字符之前可以带有整数重复计数。 例如,格式字符串 '4h' 的含义与 'hhhh' 完全相同。

    格式之间的空白字符会被忽略;但是计数及其格式字符中不可有空白字符。

    当使用某一种整数格式 ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q') 打包值 x 时,如果 x 在该格式的有效范围之外则将引发 struct.error。

    在 3.1 版更改: 在之前版本中,某些整数格式包装了超范围的值并会引发 DeprecationWarning 而不是 struct.error。

    对于 '?' 格式字符,返回值为 True 或 False。 在打包时将会使用参数对象的逻辑值。 以本机或标准 bool 类型表示的 0 或 1 将被打包,任何非零值在解包时将为 True。

    struct.Struct

    struct.Struct 是一个用于处理二进制数据的类,可以将二进制数据按照指定格式进行打包或解包。

    语法:

    class struct.Struct(format)

    参数说明:

    format:格式字符串。

    返回一个struct对象(结构体,参考C)

    1. import struct
    2. values = (1, 'abcd'.encode('utf-8'), 2.7)
    3. s = struct.Struct('I 4s f')
    4. packed_data = s.pack(*values)
    5. print(s)
    6. print(s.format)
    7. print('Original values:', values)
    8. print('Format string :', s.format)
    9. print('Uses :', s.size, 'bytes')
    10. print('Packed Value :', packed_data.hex())
    11. ‘’'
    12. <_struct.Struct object at 0x105791e90>
    13. I 4s f
    14. Original values: (1, b'abcd', 2.7)
    15. Format string : I 4s f
    16. Uses : 12 bytes
    17. Packed Value : 0100000061626364cdcc2c40
    18. ‘''

    struct.pack()

    语法:

    struct.pack(formatv1v2...)

    参数说明:

    • format:格式字符串。
    • v1, v2, ..., vn:需要转换为字节串的值。

    返回一个 bytes 对象,其中包含根据格式字符串 format 打包的值 v1v2, ... 参数个数必须与格式字符串所要求的值完全匹配。

    该函数常用于将python的数据转换为C语言中所使用的二进制数据格式。

    1. import struct
    2. n = 1024
    3. b = struct.pack('I', n)
    4. print(b) # b'\x00\x04\x00\x00'

    上述代码将一个无符号整数n转换为二进制字节串b,使用了'I'格式化字符。

    1. import struct
    2. s = 'hello'
    3. b = struct.pack('5s', bytes(s, encoding='utf-8'))
    4. print(b) # b'hello'

    上述代码将字符串s转换为定长字节串b,使用了'5s'格式化字符。

    1. import struct
    2. f = 1.23
    3. b = struct.pack('f', f)
    4. print(b) # b'\xab\x1f\x9d?'

    上述代码将单精度浮点数f转换为二进制字节串b,使用了'f'格式化字符。

    1. import struct
    2. # 定义一个结构体类型
    3. student = struct.Struct('3s I 2s')
    4. # 创建结构体对象
    5. stu = student.pack(b'Bob', 20, b'McGraw')
    6. # 解析结构体对象
    7. name, age, school = student.unpack(stu)
    8. print('name:', name.decode()) #name: Bob
    9. print('age:', age) #age: 20
    10. print('school:', school.decode()) #school: Mc

    上述代码先定义了一个结构体类型,它包含了三个元素:长度为3的字符串、一个整数和长度为2的字符串。然后通过调用 Struct.pack() 函数将结构体对象stu打包,并且使用Struct.unpack()函数将其解包。

    struct.unpack()

    语法:

    struct.unpack(format, buffer)

    根据格式字符串 format 从缓冲区 buffer 解包(假定是由 pack(format, ...) 打包)。 结果为一个元组,即使其只包含一个条目。 缓冲区的字节大小必须匹配格式所要求的大小,如 calcsize() 所示。

    1. import struct
    2. # values = (1, 'abcd'.encode('utf-8'), 2.7)
    3. # s = struct.Struct('I 4s f')
    4. # packed_data = s.pack(*values)
    5. # print(s)
    6. # print(s.format)
    7. #
    8. # print('Original values:', values)
    9. # print('Format string :', s.format)
    10. # print('Uses :', s.size, 'bytes')
    11. # print('Packed Value :', packed_data.hex())
    12. hs='0100000061626364cdcc2c40'
    13. bs=bytes.fromhex(hs)
    14. s = struct.Struct('I 4s f')
    15. values = s.unpack(bs)
    16. print(values) #(1, b'abcd', 2.700000047683716)

    1. import struct
    2. s1 = b'He is not very happy!'
    3. format = '2s 1x 2s 5x 4s 1x 6s'
    4. b = struct.unpack(format, s1)
    5. print(b) #(b'He', b'is', b'very', b'happy!')
    6. s2 = struct.pack('2s 2s 4s 6s', *b)
    7. print(s2) #b'Heisveryhappy!'

    struct.pack_into()

    struct.pack_into(formatbufferoffsetv1v2...)

    根据格式字符串 format 打包 v1v2, ... 等值并将打包的字节串写入可写缓冲区 buffer 从 offset 开始的位置。 请注意 offset 是必需的参数。

    struct.unpack_from()

    语法:

    struct.unpack_from(format, /, buffer, offset=0)

    对 buffer 从位置 offset 开始根据格式字符串 format 进行解包。 结果为一个元组,即使其中只包含一个条目。 缓冲区的字节大小从位置 offset 开始必须至少为 calcsize() 显示的格式所要求的大小。

    1. import struct
    2. import ctypes
    3. values1 = (1314, b'I love you', 3.1415) # 查看格式化字符串可知,字符串必须为字节流类型。
    4. s1 = struct.Struct('I10sf')
    5. values2 = (b'No!Go away!', 444) # 查看格式化字符串可知,字符串必须为字节流类型。
    6. s2 = struct.Struct('11sI')
    7. buff = ctypes.create_string_buffer(s1.size + s2.size)
    8. packed_data = s1.pack_into(buff, 0, *values1)
    9. s2.pack_into(buff, s1.size, *values2)
    10. s3 = struct.Struct('I10sf11sI')
    11. unpacked_data = s3.unpack_from(buff, 0)
    12. print('buff :', buff)
    13. print('Packed Value :', buff.raw.hex())
    14. print('Unpacked Type :', type(unpacked_data), ' Value:', unpacked_data)
    15. ‘’'
    16. buff :
    17. Packed Value : 2205000049206c6f766520796f750000560e49404e6f21476f20617761792100bc010000
    18. Unpacked Type : tuple'> Value: (1314, b'I love you', 3.1414999961853027, b'No!Go away!', 444)
    19. ‘''

    struct.iter_unpack(formatbuffer)

    根据格式串format从缓冲区buffer解包,结果为一个迭代器。

    struct.calcsize(format)

    返回与格式字符串 format 相对应的结构的大小(亦即 pack(format, ...) 所产生的字节串对象的大小)。

    memoryview

    memoryview 对象允许 Python 代码访问一个对象的内部数据。这个函数可以用于在 Python 中操作二进制数据,例如在处理音频、视频或图像文件时。使用memoryview()函数可以提高处理效率,因为它允许您直接访问原始数据的内存,而无需创建临时副本。

    class memoryview(object)

    创建一个引用 object 的 memoryview 。 object 必须支持缓冲区协议。支持缓冲区协议的内置对象有 bytes 和 bytearray 。

    memoryview 有 元素 的概念, 元素 指由原始 object 处理的原子内存单元。对于许多简单的类型,如 bytes 和 bytearray ,一个元素是一个字节,但其他类型,如 array.array 可能有更大的元素。

    支持通过切片和索引访问其元素。 一维切片的结果将是一个子视图:

    1. >>>v = memoryview(b'abcefg')
    2. >>>v[1]
    3. 98
    4. >>>v[-1]
    5. 103
    6. >>>v[1:4]
    7. 0x7f3ddc9f4350>
    8. >>>bytes(v[1:4])
    9. b'bce'

    如果 format 是一个来自于 struct 模块的原生格式说明符,则也支持使用整数或由整数构成的元组进行索引,并返回具有正确类型的单个 元素。 一维内存视图可以使用一个整数或由一个整数构成的元组进行索引。 多维内存视图可以使用由恰好 ndim 个整数构成的元素进行索引,ndim 即其维度。 零维内存视图可以使用空元组进行索引。

    这里是一个使用非字节格式的例子:

    1. >>>import array
    2. >>>a = array.array('l', [-11111111, 22222222, -33333333, 44444444])
    3. >>>m = memoryview(a)
    4. >>>m[0]
    5. -11111111
    6. >>>m[-1]
    7. 44444444
    8. >>>m[::2].tolist()
    9. [-11111111, -33333333]

    如果下层对象是可写的,则内存视图支持一维切片赋值。 改变大小则不被允许:

    1. >>>data = bytearray(b'abcefg')
    2. >>>v = memoryview(data)
    3. >>>v.readonly
    4. False
    5. >>>v[0] = ord(b'z')
    6. >>>data
    7. bytearray(b'zbcefg')
    8. >>>v[1:4] = b'123'
    9. >>>data
    10. bytearray(b'z123fg')
    11. >>>v[2:3] = b'spam'
    12. Traceback (most recent call last):
    13. File "", line 1, in
    14. ValueError: memoryview assignment: lvalue and rvalue have different structures
    15. >>>v[2:6] = b'spam'
    16. >>>data
    17. bytearray(b'z1spam')

    格式符为 'B', 'b' 或 'c' 的 hashable (只读) 类型的一维内存视图也是可哈希对象。 哈希被定义为 hash(m) == hash(m.tobytes()):

    1. >>>v = memoryview(b'abcefg')
    2. >>>hash(v) == hash(b'abcefg')
    3. True
    4. >>>hash(v[2:4]) == hash(b'ce')
    5. True
    6. >>>hash(v[::-2]) == hash(b'abcefg'[::-2])
    7. True

    __eq__(exporter)

    如果所指向的内容的值相等,则两个内存视图就相等,并不一定是指向同一片内存视图

    1. >>>import array
    2. >>>a = array.array('I', [1, 2, 3, 4, 5])
    3. >>>b = array.array('d', [1.0, 2.0, 3.0, 4.0, 5.0])
    4. >>>c = array.array('b', [5, 3, 1])
    5. >>>x = memoryview(a)
    6. >>>y = memoryview(b)
    7. >>>x == a == y == b
    8. True
    9. >>>x.tolist() == a.tolist() == y.tolist() == b.tolist()
    10. True
    11. >>>z = y[::-2]
    12. >>>z == c
    13. True
    14. >>>z.tolist() == c.tolist()
    15. True

    如果两边的格式字符串都不被 struct 模块所支持,则两对象比较结果总是不相等(即使格式字符串和缓冲区内容相同):

    1. >>>from ctypes import BigEndianStructure, c_long
    2. >>>class BEPoint(BigEndianStructure):
    3. _fields_ = [("x", c_long), ("y", c_long)]
    4. >>>point = BEPoint(100, 200)
    5. >>>a = memoryview(point)
    6. >>>b = memoryview(point)
    7. >>>a == point
    8. False
    9. >>>a == b
    10. False

    请注意,与浮点数的情况一样,对于内存视图对象来说,v is w 也 并不 意味着 v == w

    tobytes(order='C')

    将缓冲区中的数据作为字节串返回。 这相当于在内存视图上调用 bytes 构造器。

    1. >>>m = memoryview(b"abc")
    2. >>>m.tobytes()
    3. b'abc'
    4. >>>bytes(m)
    5. b'abc'

    3.8 新版功能: order 可以为 {'C', 'F', 'A'}。 当 order 为 'C' 或 'F' 时,原始数组的数据会被转换至 C 或 Fortran 顺序。 对于连续视图,'A' 会返回物理内存的精确副本。 特别地,内存中的 Fortran 顺序会被保留。对于非连续视图,数据会先被转换为 C 形式。 order=None 与 order='C' 是相同的。

    hex([sep[, bytes_per_sep]])

    返回一个字符串对象,其中分别以两个十六进制数码表示缓冲区里的每个字节。

    在 3.8 版更改: 与 bytes.hex() 相似, memoryview.hex() 现在支持可选的 sep 和 bytes_per_sep 参数以在十六进制输出的字节之间插入分隔符。

    tolist()

    将缓冲区内的数据以一个元素列表的形式返回。

    1. >>>memoryview(b'abc').tolist()
    2. [97, 98, 99]
    3. >>>import array
    4. >>>a = array.array('d', [1.1, 2.2, 3.3])
    5. >>>m = memoryview(a)
    6. >>>m.tolist()
    7. [1.1, 2.2, 3.3]

    toreadonly()

    返回 memoryview 对象的只读版本。 原始的 memoryview 对象不会被改变。

    1. >>>m = memoryview(bytearray(b'abc'))
    2. >>>mm = m.toreadonly()
    3. >>>mm.tolist()
    4. [97, 98, 99]
    5. >>>mm[0] = 42
    6. Traceback (most recent call last):
    7. File "", line 1, in
    8. TypeError: cannot modify read-only memory
    9. >>>m[0] = 43
    10. >>>mm.tolist()
    11. [43, 98, 99]

    release()

    释放由内存视图对象所公开的底层缓冲区。 许多对象在被视图所获取时都会采取特殊动作(例如,bytearray 将会暂时禁止调整大小);因此,调用 release() 可以方便地尽早去除这些限制(并释放任何多余的资源)。

    在此方法被调用后,任何对视图的进一步操作将引发 ValueError (release() 本身除外,它可以被多次调用):

    1. >>>m = memoryview(b'abc')
    2. >>>m.release()
    3. >>>m[0]
    4. Traceback (most recent call last):
    5. File "", line 1, in
    6. ValueError: operation forbidden on released memoryview object

    使用 with 语句,可以通过上下文管理协议达到类似的效果:

    1. >>>with memoryview(b'abc') as m:
    2. m[0]
    3. 97
    4. >>>m[0]
    5. Traceback (most recent call last):
    6. File "", line 1, in
    7. ValueError: operation forbidden on released memoryview object

    cast(format[, shape])

    将内存视图转化为新的格式或形状。 shape 默认为 [byte_length//new_itemsize],这意味着结果视图将是一维的。 返回值是一个新的内存视图,但缓冲区本身不会被复制。 支持的转化有 1D -> C-contiguous 和 C-contiguous -> 1D。

    目标格式被限制为 struct 语法中的单一元素的原生格式。 这些格式中的一种必须为字节格式 ('B', 'b' 或 'c')。 结果的字节长度必须与原始长度相同。 请注意全部字节长度可能取决于具体操作系统。

    将 1D/long 转换为 1D/unsigned bytes:

    1. >>>import array
    2. >>>a = array.array('l', [1,2,3])
    3. >>>x = memoryview(a)
    4. >>>x.format
    5. 'l'
    6. >>>x.itemsize
    7. 8
    8. >>>len(x)
    9. 3
    10. >>>x.nbytes
    11. 24
    12. >>>y = x.cast('B')
    13. >>>y.format
    14. 'B'
    15. >>>y.itemsize
    16. 1
    17. >>>len(y)
    18. 24
    19. >>>y.nbytes
    20. 24

    将 1D/unsigned bytes 转换为 1D/char:

    1. >>>b = bytearray(b'zyz')
    2. >>>x = memoryview(b)
    3. >>>x[0] = b'a'
    4. Traceback (most recent call last):
    5. ...
    6. TypeError: memoryview: invalid type for format 'B'
    7. >>>y = x.cast('c')
    8. >>>y[0] = b'a'
    9. >>>b
    10. bytearray(b'ayz')

    将 1D/bytes 转换为 3D/ints 再转换为 1D/signed char:

    1. >>>import struct
    2. >>>buf = struct.pack("i"*12, *list(range(12)))
    3. >>>x = memoryview(buf)
    4. >>>y = x.cast('i', shape=[2,2,3])
    5. >>>y.tolist()
    6. [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]
    7. >>>y.format
    8. 'i'
    9. >>>y.itemsize
    10. 4
    11. >>>len(y)
    12. 2
    13. >>>y.nbytes
    14. 48
    15. >>>z = y.cast('b')
    16. >>>z.format
    17. 'b'
    18. >>>z.itemsize
    19. 1
    20. >>>len(z)
    21. 48
    22. z.nbytes
    23. 48

    将 1D/unsigned long 转换为 2D/unsigned long:

    1. >>>buf = struct.pack("L"*6, *list(range(6)))
    2. >>>x = memoryview(buf)
    3. >>>y = x.cast('L', shape=[2,3])
    4. >>>len(y)
    5. 2
    6. >>>y.nbytes
    7. 48
    8. >>>y.tolist()
    9. [[0, 1, 2], [3, 4, 5]]

    obj

    内存视图的下层对象:

    1. >>>b = bytearray(b'xyz')
    2. >>>m = memoryview(b)
    3. >>>m.obj is b
    4. True

    nbytes

    nbytes == product(shape) * itemsize == len(m.tobytes())。 这是数组在连续表示时将会占用的空间总字节数。 它不一定等于 len(m):

    1. >>>import array
    2. >>>a = array.array('i', [1,2,3,4,5])
    3. >>>m = memoryview(a)
    4. >>>len(m)
    5. 5
    6. >>>m.nbytes
    7. 20
    8. >>>y = m[::2]
    9. >>>len(y)
    10. 3
    11. >>>y.nbytes
    12. 12
    13. >>>len(y.tobytes())
    14. 12

    多维数组:

    1. >>>import struct
    2. >>>buf = struct.pack("d"*12, *[1.5*x for x in range(12)])
    3. >>>x = memoryview(buf)
    4. >>>y = x.cast('d', shape=[3,4])
    5. >>>y.tolist()
    6. [[0.0, 1.5, 3.0, 4.5], [6.0, 7.5, 9.0, 10.5], [12.0, 13.5, 15.0, 16.5]]
    7. >>>len(y)
    8. 3
    9. >>>y.nbytes
    10. 96

    readonly

    一个表明内存是否只读的布尔值。

    format

    一个字符串,包含视图中每个元素的格式(表示为 struct 模块样式)。 内存视图可以从具有任意格式字符串的导出器创建,但某些方法 (例如 tolist()) 仅限于原生的单元素格式。

    在 3.3 版更改: 格式 'B' 现在会按照 struct 模块语法来处理。 这意味着 memoryview(b'abc')[0] == b'abc'[0] == 97。

    itemsize

    memoryview 中每个元素以字节表示的大小:

    1. >>>import array, struct
    2. >>>m = memoryview(array.array('H', [32000, 32001, 32002]))
    3. >>>m.itemsize
    4. 2
    5. >>>m[0]
    6. 32000
    7. >>>struct.calcsize('H') == m.itemsize
    8. True

    ndim

    一个整数,表示内存所代表的多维数组具有多少个维度。

    shape

    一个整数元组,通过 ndim 的长度值给出内存所代表的 N 维数组的形状。

    在 3.3 版更改: 当 ndim = 0 时值为空元组而不再为 None。

    strides

    一个整数元组,通过 ndim 的长度给出以字节表示的大小,以便访问数组中每个维度上的每个元素。

    在 3.3 版更改: 当 ndim = 0 时值为空元组而不再为 None。

    suboffsets

    供 PIL 风格的数组内部使用。 该值仅作为参考信息。

    c_contiguous

    一个表明内存是否为 C-contiguous 的布尔值。

    3.3 新版功能.

    f_contiguous

    一个表明内存是否为 Fortran contiguous 的布尔值。

    3.3 新版功能.

    contiguous

    一个表明内存是否为 contiguous 的布尔值。

    3.3 新版功能.

    codecs

    这个模块定义了标准 Python 编解码器(编码器和解码器)的基类并提供对内部 Python 编解码器注册表的访问,该注册表负责管理编解码器和错误处理的查找过程。 大多数标准编解码器都属于 文本编码格式,它们可将文本编码为字节串(以及将字节串解码为文本),但也提供了一些将文本编码为文本,以及将字节串编码为字节串的编解码器。 自定义编解码器可以在任意类型间进行编码和解码,但某些模块特性被限制为仅适用于 文本编码格式 或将数据编码为 bytes 的编解码器。

    编码格式

    字符串在系统内部存储为 U+0000--U+10FFFF 范围内的码位序列。

    一旦字符串对象要在 CPU 和内存以外使用,字节的大小端顺序和字节数组的存储方式就成为一个影响因素。 如同使用其他编解码器一样,将字符串序列化为字节序列被称为 编码,而从字节序列重建字符串被称为 解码

    Python 自带了许多内置的编解码器,它们的实现或者是通过 C 函数,或者是通过映射表。并提供了一些常见别名以及编码格式通常针对的语言。 别名和语言列表都不是详尽无遗的。有些常见编码格式可以绕过编解码器查找机制来提升性能。 这些优化机会对于 CPython 来说仅能通过一组有限的别名(大小写不敏感)来识别:utf-8, utf8, latin-1, latin1, iso-8859-1, iso8859-1, mbcs (Windows 专属), ascii, us-ascii, utf-16, utf16, utf-32, utf32, 也包括使用下划线替代连字符的的形式。 使用这些编码格式的其他别名可能会导致更慢的执行速度。

    常见的中文相关编码:

    编码

    别名

    语言

    ascii

    646, us-ascii

    英语

    big5

    big5-tw, csbig5

    繁体中文

    big5hkscs

    big5-hkscs, hkscs

    繁体中文

    gb2312

    chinese, csiso58gb231280, euc-cn, euccn,

    eucgb2312-cn, gb2312-1980, gb2312-80, iso-ir-58

    简体中文

    gbk

    936, cp936, ms936

    统一汉语

    gb18030

    gb18030-2000

    统一汉语

    hz

    hzgb, hz-gb, hz-gb-2312

    简体中文

    utf_32

    U32, utf32

    所有语言

    utf_32_be

    UTF-32BE

    所有语言

    utf_32_le

    UTF-32LE

    所有语言

    utf_16

    U16, utf16

    所有语言

    utf_16_be

    UTF-16BE

    所有语言

    utf_16_le

    UTF-16LE

    所有语言

    utf_7

    U7, unicode-1-1-utf-7

    所有语言

    utf_8

    U8, UTF, utf8, cp65001

    所有语言

    utf_8_sig

    所有语言

    二进制转换

    以下编解码器提供了二进制转换: bytes-like object 到 bytes 的映射。 它们不被 bytes.decode() 所支持(该方法只生成 str 类型的输出)。

    编码

    别名

    含意

    编码器/解码器

    base64_codec 1

    base64, base_64

    将操作数转换为多行 MIME base64 (结果总是包含一个末尾的 '\n')

    在 3.4 版更改: 接受任意 bytes-like object作为输入用于编码和解码

    base64.encodebytes()/ base64.decodebytes()

    bz2_codec

    bz2

    使用bz2压缩操作数

    bz2.compress() / bz2.decompress()

    hex_codec

    hex

    将操作数转换为十六进制表示,每个字节有两位数

    binascii.b2a_hex() / binascii.a2b_hex()​​​​​​​

    quopri_codec

    quopri, quotedprintable, quoted_printable

    将操作数转换为 MIME 带引号的可打印数据

    quopri.encode() 且 quotetabs=True / quopri.decode()

    uu_codec

    uu

    使用uuencode转换操作数

    uu.encode() / uu.decode()

    zlib_codec

    zip, zlib

    使用gzip压缩操作数

    zlib.compress() / zlib.decompress()​​​​​​​

    codecs.encode(objencoding='utf-8'errors='strict')

    使用为 encoding 注册的编解码器对 obj 进行编码。

    可以给定 Errors 以设置所需要的错误处理方案。 默认的错误处理方案 'strict' 表示编码错误将引发 ValueError (或更特定编解码器相关的子类,例如 UnicodeEncodeError)。

    codecs.decode(objencoding='utf-8'errors='strict')

    使用为 encoding 注册的编解码器对 obj 进行解码。

    codecs.open()

    语法格式为:

    codecs.open(filenamemode='r'encoding=Noneerrors='strict'buffering=- 1)

    使用给定的 mode 打开已编码的文件并返回一个 StreamReaderWriter 的实例,提供透明的编码/解码。 默认的文件模式为 'r',表示以读取模式打开文件。

    encoding 指定文件所要使用的编码格式。 允许任何编码为字节串或从字节串解码的编码格式,而文件方法所支持的数据类型则取决于所使用的编解码器。

    可以指定 errors 来定义错误处理方案。 默认值 'strict' 表示在出现编码错误时引发 ValueError。

    buffering 的含义与内置 open() 函数中的相同。 默认值 -1 表示将使用默认的缓冲区大小。

    codecs.EncodedFile()

    语法为:

    codecs.EncodedFile(filedata_encodingfile_encoding=Noneerrors='strict')

    返回一个 StreamRecoder 实例,它提供了 file 的透明转码包装版本。 当包装版本被关闭时原始文件也会被关闭。

    写入已包装文件的数据会根据给定的 data_encoding 解码,然后以使用 file_encoding 的字节形式写入原始文件。 从原始文件读取的字节串将根据 file_encoding 解码,其结果将使用 data_encoding 进行编码。

    如果 file_encoding 未给定,则默认为 data_encoding。

    可以指定 errors 来定义错误处理方案。 默认值 'strict' 表示在出现编码错误时引发 ValueError。

    codecs.iterencode(iterator, encoding, errors='strict', **kwargs)

    使用增量式编码器通过迭代来编码由 iterator 所提供的输入。 此函数属于 生成器(generator)。 errors 参数(以及任何其他关键字参数)会被传递给增量式编码器。

    此函数要求编解码器接受 str 对象形式的文本进行编码。 因此它不支持字节到字节的编码器,例如 base64_codec。

    codecs.iterdecode(iterator, encoding, errors='strict', **kwargs)

    使用增量式解码器通过迭代来解码由 iterator 所提供的输入。 此函数属于生成器( generator)。 errors 参数(以及任何其他关键字参数)会被传递给增量式解码器。

    此函数要求编解码器接受 bytes 对象进行解码。 因此它不支持文本到文本的编码器,例如 rot_13,但是 rot_13 可以通过同样效果的 iterencode() 来使用。

    codecs.lookup(encoding)

    在 Python 编解码器注册表中查找编解码器信息,并返回一个 CodecInfo 对象。

    class codecs.CodecInfo()

    语法为:

    class codecs.CodecInfo(encodedecodestreamreader=Nonestreamwriter=Noneincrementalencoder=Noneincrementaldecoder=Nonename=None)

    编解码器细节信息

    • name: 编码名称
    • encode、decode:无状态的编码和解码函数。 它们必须是具有与 Codec 的 encode() 和 decode() 方法相同接口的函数或方法。 这些函数或方法应当工作于无状态的模式。
    • incrementalencoder、incrementaldecoder:增量式的编码器和解码器类或工厂函数。 这些函数必须分别提供由基类 IncrementalEncoder 和 IncrementalDecoder 所定义的接口。 增量式编解码器可以保持状态。
    • streamwriter、streamreader:流式写入器和读取器类或工厂函数。 这些函数必须分别提供由基类 StreamWriter 和 StreamReader 所定义的接口。 流式编解码器可以保持状态。

    codecs.getencoder(encoding)

    查找给定编码的编解码器并返回其编码器函数。

    codecs.getdecoder(encoding)

    查找给定编码的编解码器并返回其解码器函数。

    codecs.getincrementalencoder(encoding)

    查找给定编码的编解码器并返回其增量式编码器类或工厂函数。

    codecs.getincrementaldecoder(encoding)

    查找给定编码的编解码器并返回其增量式解码器类或工厂函数。

    codecs.getreader(encoding)

    查找给定编码的编解码器并返回其StreamReader 类或工厂函数。

    codecs.getwriter(encoding)

    查找给定编码的编解码器并返回其 StreamWriter类或工厂函数。

    codecs.register(search_function)

    注册一个编解码器搜索函数。 搜索函数预期接收一个参数,即全部以小写字母表示的编码格式名称,其中中连字符和空格会被转换为下划线,并返回一个 CodecInfo 对象。 在搜索函数无法找到给定编码格式的情况下,它应当返回 None。

    在 3.9 版更改: 连字符和空格会被转换为下划线。

    codecs.unregister(search_function)

    注销一个编解码器搜索函数并清空注册表缓存。 如果指定搜索函数未被注册,则不做任何操作。

    codecs.register_error(nameerror_handler)

    在名称 name 之下注册错误处理函数 error_handler。 当 name 被指定为错误形参时,error_handler 参数所指定的对象将在编码和解码期间发生错误的情况下被调用,

    对于编码操作,将会调用 error_handler 并传入一个 UnicodeEncodeError 实例,其中包含有关错误位置的信息。 错误处理程序必须引发此异常或别的异常,或者也可以返回一个元组,其中包含输入的不可编码部分的替换对象,以及应当继续进行编码的位置。 替换对象可以为 str 或 bytes 类型。 如果替换对象为字节串,编码器将简单地将其复制到输出缓冲区。 如果替换对象为字符串,编码器将对替换对象进行编码。 对原始输入的编码操作会在指定位置继续进行。 负的位置值将被视为相对于输入字符串的末尾。 如果结果位置超出范围则将引发 IndexError。

    解码和转换的做法很相似,不同之处在于将把 UnicodeDecodeError 或 UnicodeTranslateError 传给处理程序,并且来自错误处理程序的替换对象将被直接放入输出。

  • 相关阅读:
    java计算机毕业设计web家庭财务管理系统MyBatis+系统+LW文档+源码+调试部署
    Linux内存管理(二十三):slub 分配器之kmem_cache_create
    upload-labs靶场通关指南(14-15关)
    每日LeetCode——Java版(一)
    好用的工作日志软件
    camunda_06_quickstart_springboot
    Kafka入门教程与详解(一)
    taobao.trade.get( 获取单笔交易的部分信息(性能高),淘宝R2接口,淘宝开发平台oAuth2.0接口
    llvm dominator
    【模电实验】【精简版】【验证性实验——两级阻容耦合负反馈放大器实验】
  • 原文地址:https://blog.csdn.net/spiritx/article/details/132719680