资讯专栏INFORMATION COLUMN

Python标准库---14、内置类型:二进制序列类型 (memoryview)

yacheng / 3655人阅读

摘要:对于更高的维度,其长度等于表示的嵌套列表的长度。这是数组在连续表示时将会占用的空间总字节数。该值仅作为参考信息。新版功能一个表明内存是否为的布尔值。新版功能上一篇文章标准库内置类型二进制序列类型下一篇文章标准库内置类型集合类型映射类型

上一篇文章:Python标准库---13、内置类型:二进制序列类型 ( bytes, bytearray)
下一篇文章:Python标准库---15、内置类型:集合类型、映射类型
内存视图

memoryview 对象允许 Python 代码访问一个对象的内部数据,只要该对象支持 缓冲区协议 而无需进行拷贝。

class memoryview(obj)

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

memoryview 具有 元素 的概念,即由原始对象 obj 所处理的基本内存单元。 对于许多简单类型例如 bytes 和 bytearray 来说,一个元素就是一个字节,但是其他的类型例如 array.array 可能有更大的元素。

len(view) 与 tolist 的长度相等。 如果 view.ndim = 0,则其长度为 1。 如果 view.ndim = 1,则其长度等于 view 中元素的数量。 对于更高的维度,其长度等于表示 view 的嵌套列表的长度。 itemsize 属性可向你给出单个元素所占的字节数。

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

    >>> v = memoryview(b"abcefg")
    >>> v[1]
    98
    >>> v[-1]
    103
    >>> v[1:4]
    
    >>> bytes(v[1:4])
    b"bce"

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

这里是一个使用非字节格式的例子:
    >>> import array
    >>> a = array.array("l", [-11111111, 22222222, -33333333, 44444444])
    >>> m = memoryview(a)
    >>> m[0]
    -11111111
    >>> m[-1]
    44444444
    >>> m[::2].tolist()
    [-11111111, -33333333]

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

    >>> data = bytearray(b"abcefg")
    >>> v = memoryview(data)
    >>> v.readonly
    False
    >>> v[0] = ord(b"z")
    >>> data
    bytearray(b"zbcefg")
    >>> v[1:4] = b"123"
    >>> data
    bytearray(b"z123fg")
    >>> v[2:3] = b"spam"
    Traceback (most recent call last):
      File "", line 1, in 
    ValueError: memoryview assignment: lvalue and rvalue have different structures
    >>> v[2:6] = b"spam"
    >>> data
    bytearray(b"z1spam")

由带有格式符号 "B", "b" 或 "c" 的可哈希(只读)类型构成的一维内存视图同样是可哈希的。 哈希定义为 hash(m) == hash(m.tobytes()):

    >>> v = memoryview(b"abcefg")
    >>> hash(v) == hash(b"abcefg")
    True
    >>> hash(v[2:4]) == hash(b"ce")
    True
    >>> hash(v[::-2]) == hash(b"abcefg"[::-2])
    True

在 3.3 版更改: 一维内存视图现在可以被切片。 带有格式符号 "B", "b" 或 "c" 的一维内存视图现在是可哈希的。

在 3.4 版更改: 内存视图现在会自动注册为 collections.abc.Sequence

在 3.5 版更改: 内存视图现在可使用整数元组进行索引。

memoryview 具有以下一些方法:

__eq__(exporter)

memoryview 与 PEP 3118 中的导出器这两者如果形状相同,并且如果当使用 struct 语法解读操作数的相应格式代码时所有对应值都相同,则它们就是等价的。

对于 tolist() 当前所支持的 struct 格式字符串子集,如果 v.tolist() == w.tolist() 则 v 和 w 相等:

        >>> import array
        >>> 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
        >>> x.tolist() == a.tolist() == y.tolist() == b.tolist()
        True
        >>> z = y[::-2]
        >>> z == c
        True
        >>> z.tolist() == c.tolist()
        True

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

        >>> from ctypes import BigEndianStructure, c_long
        >>> class BEPoint(BigEndianStructure):
        ...     _fields_ = [("x", c_long), ("y", c_long)]
        ...
        >>> point = BEPoint(100, 200)
        >>> a = memoryview(point)
        >>> b = memoryview(point)
        >>> a == point
        False
        >>> a == b
        False

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

在 3.3 版更改: 之前的版本比较原始内存时会忽略条目的格式与逻辑数组结构。

tobytes()

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

        >>> m = memoryview(b"abc")
        >>> m.tobytes()
        b"abc"
        >>> bytes(m)
        b"abc"

对于非连续数组,结果等于平面化表示的列表,其中所有元素都转换为字节串。 tobytes() 支持所有格式字符串,不符合 struct 模块语法的那些也包括在内。

hex()

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

        >>> m = memoryview(b"abc")
        >>> m.hex()
        "616263"

3.5 新版功能.

tolist()

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

        >>> memoryview(b"abc").tolist()
        [97, 98, 99]
        >>> import array
        >>> a = array.array("d", [1.1, 2.2, 3.3])
        >>> m = memoryview(a)
        >>> m.tolist()
        [1.1, 2.2, 3.3]

在 3.3 版更改: tolist() 现在支持 struct 模块语法中的所有单字符原生格式以及多维表示形式。

release()

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

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

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

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

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

3.2 新版功能.

cast(format[, shape])

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

目标格式仅限于 struct 语法中的单一元素原生格式。 其中一种格式必须为字节格式 ("B", "b" 或 "c")。 结果的字节长度必须与原始长度相同。

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

        >>> import array
        >>> a = array.array("l", [1,2,3])
        >>> x = memoryview(a)
        >>> x.format
        "l"
        >>> x.itemsize
        8
        >>> len(x)
        3
        >>> x.nbytes
        24
        >>> y = x.cast("B")
        >>> y.format
        "B"
        >>> y.itemsize
        1
        >>> len(y)
        24
        >>> y.nbytes
        24

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

        >>> b = bytearray(b"zyz")
        >>> x = memoryview(b)
        >>> x[0] = b"a"
        Traceback (most recent call last):
          File "", line 1, in 
        ValueError: memoryview: invalid value for format "B"
        >>> y = x.cast("c")
        >>> y[0] = b"a"
        >>> b
        bytearray(b"ayz")

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

       >>> 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]]]
       >>> y.format
       "i"
       >>> y.itemsize
       4
       >>> len(y)
       2
       >>> y.nbytes
       48
       >>> z = y.cast("b")
       >>> z.format
       "b"
       >>> z.itemsize
       1
       >>> len(z)
       48
       >>> z.nbytes
       48

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

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

3.3 新版功能.

在 3.5 版更改: 当转换为字节视图时,源格式将不再受限。

还存在一些可用的只读属性:

obj

内存视图的下层对象:

        >>> b  = bytearray(b"xyz")
        >>> m = memoryview(b)
        >>> m.obj is b
        True

3.3 新版功能.

nbytes

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

        >>> import array
        >>> a = array.array("i", [1,2,3,4,5])
        >>> m = memoryview(a)
        >>> len(m)
        5
        >>> m.nbytes
        20
        >>> y = m[::2]
        >>> len(y)
        3
        >>> y.nbytes
        12
        >>> len(y.tobytes())
        12

多维数组:

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

3.3 新版功能.

readonly

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

format

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

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

itemsize

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

        >>> import array, struct
        >>> m = memoryview(array.array("H", [32000, 32001, 32002]))
        >>> m.itemsize
        2
        >>> m[0]
        32000
        >>> struct.calcsize("H") == m.itemsize
        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 新版功能.

上一篇文章:Python标准库---13、内置类型:二进制序列类型 ( bytes, bytearray)
下一篇文章:Python标准库---15、内置类型:集合类型、映射类型

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44001.html

相关文章

  • Python学习之路21-序列构成的数组

    摘要:第行把具名元组以的形式返回。对序列使用和通常号两侧的序列由相同类型的数据所构成当然不同类型的也可以相加,返回一个新序列。从上面的结果可以看出,它虽抛出了异常,但仍完成了操作查看字节码并不难,而且它对我们了解代码背后的运行机制很有帮助。 《流畅的Python》笔记。接下来的三篇都是关于Python的数据结构,本篇主要是Python中的各序列类型 1. 内置序列类型概览 Python标准库...

    ralap 评论0 收藏0
  • Python标准---15、内置类型:集合类型、映射类型

    摘要:目前有两种内置集合类型,和。两个类的构造器具有相同的作用方式返回一个新的或对象,其元素来自于。要表示由集合对象构成的集合,所有的内层集合必须为对象。目前仅有一种标准映射类型字典。 上一篇文章:Python标准库---14、内置类型:二进制序列类型 (memoryview)下一篇文章:Python标准库---16、内置类型:上下文管理器类型、其他、特殊属性 集合类型 --- set, ...

    kycool 评论0 收藏0
  • Python标准---12、内置类型:文本序列类型(str)

    摘要:上一篇文章标准库内置类型迭代器类型序列类型下一篇文章标准库内置类型二进制序列类型文本序列类型在中处理文本数据是使用对象,也称为字符串。正式的定义为十进制数字符就是一般分类中的字符。 上一篇文章:Python标准库---11、内置类型:迭代器类型、序列类型(list-typle-range)下一篇文章:Python标准库---13、内置类型:二进制序列类型 ( bytes, bytear...

    luoyibu 评论0 收藏0
  • 流畅的python读书笔记-第九章-符合Python风格的对象

    摘要:以便于用户理解的方式返回对象的字符串表示形式。函数会调用函数,对来说,输出的是一个有序对。此外,还有用于支持内置的构造函数的方法。可散列实现了方法,使用推荐的异或运算符计算实例属性的散列值私有属性最好用命名规则来实现这种方式有好有坏 绝对不要使用两个前导下划线,这是很烦人的自私行为。——Ian Bicking 对象表示形式 repr()  以便于开发者理解的方式返回对象的字符串表示形式...

    fai1017 评论0 收藏0
  • 流畅的python

    摘要:流畅的中有很多奇技淫巧,整本书都在强调如何最大限度地利用标准库。常见的扁平序列包括,,等。数组支持所有跟可变序列有关的操作,包括和。和用于指定列表的区间,默认是使用整个列表。但是元组的赋值不被允许,当异发生时 流畅的python中有很多奇技淫巧,整本书都在强调如何最大限度地利用Python 标准库。介绍了很多python的不常用的数据类型、操作、库等,对于入门python后想要提升对p...

    Alan 评论0 收藏0

发表评论

0条评论

yacheng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<