跳到主要内容

Python memoryview() 函数

在了解什么是内存视图之前,我们首先需要了解 Python 的缓冲区协议。

Python 缓冲区协议

缓冲区协议提供了一种访问对象内部数据的方式。这些内部数据是内存数组或缓冲区。

缓冲区协议允许一个对象暴露其内部数据(缓冲区),另一个对象访问这些缓冲区而无需中间复制。

这个协议只能在 C-API 级别访问,不能使用我们的常规代码库访问。

因此,为了在常规 Python 代码库中暴露相同的协议,存在内存视图。

什么是内存视图?

内存视图是一种在 Python 中安全暴露缓冲区协议的方式。

它允许你通过创建内存视图对象来访问对象的内部缓冲区。

为什么缓冲区协议和内存视图很重要?

我们需要记住,每当我们对一个对象执行某些操作(调用对象的函数、切片数组)时,Python 需要创建该对象的副本

如果我们有大量数据需要处理(例如图像的二进制数据),我们将不必要地创建大块数据的副本,这几乎没有用处。

使用缓冲区协议,我们可以给另一个对象访问/修改大数据的权限,而无需复制它。这使程序使用更少的内存并提高执行速度。

Python memoryview() 语法

要使用 memoryview() 暴露缓冲区协议,我们使用以下语法:

memoryview(obj)

memoryview() 参数

memoryview() 函数接受单个参数:

  • obj - 要暴露其内部数据的对象。obj 必须支持缓冲区协议(bytes, bytearray

从 memoryview() 返回值

memoryview() 函数返回一个内存视图对象。

示例 1:memoryview() 在 Python 中如何工作?

# 随机字节数组
random_byte_array = bytearray('ABC', 'utf-8')

mv = memoryview(random_byte_array)

# 访问内存视图的零索引
print(mv[0])

# 从内存视图创建字节
print(bytes(mv[0:2]))

# 从内存视图创建列表
print(list(mv[0:3]))

输出

65
b'AB'
[65, 66, 67]

这里,我们从字节数组 random_byte_array 创建了一个内存视图对象 mv。

然后,我们访问了 mv 的第 0 个索引,'A',并打印它(输出 ASCII 值 - 65)。

再次,我们访问了 mv 的索引 0 和 1,'AB',并将它们转换为字节。

最后,我们访问了 mv 的所有索引并将其转换为列表。由于内部 bytearray 以 ASCII 值存储字母,输出是 A、B 和 C 的 ASCII 值列表。

示例 2:使用内存视图修改内部数据

# 随机字节数组
random_byte_array = bytearray('ABC', 'utf-8')
print('更新前:', random_byte_array)

mv = memoryview(random_byte_array)

# 将 mv 的第 1 个索引更新为 Z
mv[1] = 90
print('更新后:', random_byte_array)

输出

更新前: bytearray(b'ABC')
更新后: bytearray(b'AZC')

在这里,我们将内存视图的第一个索引更新为90,即 Z 的ASCII值。

由于内存视图对象 mv 引用相同的缓冲区/内存,所以更新 mv 中的索引也会更新 random_byte_array