说说 Python 的内存视图

851 阅读2分钟

Python 的内存视图(memoryview)是一个内置类,它能取出数组中的某一部分作为切片进行处理。切片的任何变化都会影响到数组。

NumPy 的作者 Travis Oliphant 是这样看待内存视图的:内存视图其实是泛化和去数学化的 NumPy 数组。它让我们可以在不需要复制内容的前提下,实现在数据结构之间共享内存。其中数据结构可以是任何形式,比如 PIL 图片 、SQLite 数据库和 NumPy 数组等等。对于处理大型数据集合的场景,这个功能非常重要。

PIL:Python Imaging Library,是 python 第三方图像处理库。

memoryview.cast() 方法能以不同的方式读写同一块内存数据,而且是以字节级别进行操作。

Luciano Ramalho 举了一个示例:利用 memoryview 如何准确地修改一个数组中的某个字节数据。

numbers = array.array('h', [-2, -1, 0, 1, 2])
memv = memoryview(numbers)
logging.info('len(memv) -> %s', len(memv))

logging.info('memv[0] -> %s', memv[0])

memv_oct = memv.cast('B')
list = memv_oct.tolist()
logging.info('list -> %s', list)

memv_oct[5] = 4
logging.info('numbers -> %s', numbers)

运行结果:

INFO - len(memv) -> 5
INFO - memv[0] -> -2
INFO - list -> [254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
INFO - numbers -> array('h', [-2, -1, 1024, 1, 2])
  1. 首先创建一个含有 5 个短整型有符号整数的数组;
  2. 接着创建这个数组的内存视图。可以发现它跟数组有着相同的元素个数,而且里面所包含的元素也与数组相同;
  3. 然后把这个有符号整数的内存视图转换为无符号字符的内存视图。会发现这个新的内存视图变为拥有 10 个元素的数组;
  4. 接着在新的内存视图中,把索引位置为 5 的字节赋值成 4,也就是修改占 2 个字节整数的高位字节。这样原数组中的第 3 个值就变为 1024(256 × 4)。