Python-- memryview 介绍
Python 中的 memoryview
memoryview 是 Python 提供的一个内建类,允许你在不复制数据的情况下操作字节数据。它提供了一种有效的方式来访问和操作可变数据类型(如字节对象、字节数组、bytearray 等)的内存数据。
memoryview 对象能够访问数据的内部内存,不需要复制数据,从而提供更高效的内存使用和操作。它对于处理大数据、图像、音频、二进制文件等非常有用。
1. memoryview 基本概念
- 内存视图(memory view) 是一种可以在原始数据(如
bytearray或bytes对象)上创建引用,而不需要复制数据的方法。 - 它允许你按需切片、读取和修改字节数据。
- 支持多维数组(例如,NumPy 数组)视图,类似于数组切片操作。
2. 创建和使用 memoryview
可以通过 memoryview() 函数创建一个内存视图对象,传入的数据对象必须支持缓冲区协议(例如 bytes 或 bytearray)。
基本示例:
# 创建一个 bytes 对象
data = bytearray(b"hello world")
# 创建一个 memoryview 对象
mv = memoryview(data)
# 访问第一个元素
print(mv[0]) # 输出: 104 (对应 'h' 的 ASCII 值)
# 修改 memoryview 中的元素
mv[0] = 72 # 'H'
print(data) # 输出: bytearray(b'Hello world')
memoryview创建后,可以直接像访问列表一样访问数据,但它并不会复制数据。
3. 内存视图的切片
内存视图支持切片,允许你操作和访问数据的子集。这样可以有效避免不必要的内存拷贝。
data = bytearray(b"hello world")
mv = memoryview(data)
# 切片操作
slice_view = mv[0:5] # 访问前5个字节
print(slice_view.tobytes()) # 输出: b'hello'
# 切片修改
slice_view[0] = 72 # 'H'
print(data) # 输出: bytearray(b'Hello world')
- 注意:
tobytes()方法可以将memoryview转换回字节对象。
4. 支持多维数据(如 NumPy 数组)
memoryview 不仅仅可以应用于一维的 bytes 或 bytearray,它也可以用来处理多维数据(例如通过 numpy 创建的数组)。
示例:
import numpy as np
# 创建一个二维 numpy 数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
# 创建 memoryview
mv = memoryview(arr)
# 访问和修改内存视图
print(mv[0, 0]) # 输出: 1
mv[0, 0] = 10
print(arr) # 输出: [[10 2 3] [ 4 5 6]]
- 对于多维数组,
memoryview使用逗号(,)进行索引和切片。
5. 读取和写入 memoryview
memoryview 使你能够在不创建副本的情况下,读取和修改原始数据。你可以用它来高效地处理和转换数据。
# 创建一个 bytearray
data = bytearray(b"hello")
# 创建 memoryview
mv = memoryview(data)
# 读取数据
print(mv[1]) # 输出: 101 (对应 'e')
# 修改数据
mv[1] = 105 # 'i'
print(data) # 输出: bytearray(b'hi')
memoryview不会复制数据,它直接修改原始数据。
6. memoryview 的方法和属性
memoryview 提供了一些有用的方法和属性来访问和操作数据:
tobytes():返回内存视图的字节对象副本。tolist():返回内存视图的列表副本(适用于多维数据)。format:返回数据的格式字符串。ndim:返回视图的维度数。shape:返回数据的形状(适用于多维数据)。itemsize:返回每个元素的大小(以字节为单位)。readonly:检查视图是否是只读的。
示例:
data = bytearray(b"hello world")
# 创建 memoryview
mv = memoryview(data)
# 获取数据的字节副本
bytes_copy = mv.tobytes()
print(bytes_copy) # 输出: b'hello world'
# 获取数据的元素大小
print(mv.itemsize) # 输出: 1,因为每个字节的大小是1
# 检查是否只读
print(mv.readonly) # 输出: False
# 获取数据的格式
print(mv.format) # 输出: 'B' 表示无符号字节
7. memoryview 和 bytearray
bytearray 是一个支持缓冲区协议的对象,因此可以直接与 memoryview 交互。通常,memoryview 用于高效地操作 bytearray、bytes 或类似对象。
示例:
data = bytearray(b"hello world")
# 创建 memoryview
mv = memoryview(data)
# 访问并修改数据
print(mv[0]) # 输出: 104 ('h' 的 ASCII 值)
mv[0] = 72 # 'H'
print(data) # 输出: bytearray(b'Hello world')
8. memoryview 的优点
- 性能:
memoryview允许对大数据对象(如大型字节数组、图片、音频数据等)进行切片和修改时不进行复制,节省内存。 - 内存共享:多个
memoryview对象可以共享同一块内存区域,因此更适合大规模数据操作。 - 灵活性:能够访问和修改多维数组的数据,特别适合与
NumPy数组配合使用。
总结
memoryview 提供了一个高效的方式来操作字节数据,避免了不必要的数据复制,尤其在处理大量数据时,能够显著提高性能。通过 memoryview,你可以在不创建副本的情况下切片、读取和修改数据,从而有效节省内存,尤其适用于处理大文件、图像或数组等场景。
memoryview.cast() 是 Python 中 memoryview 对象的一个方法,允许你对内存视图的内容进行类型转换。通过 cast() 方法,你可以重新解释原始数据的结构,使其以不同的数据类型或格式进行访问,而不需要复制数据。
memoryview.cast() 的基本用途
cast() 方法用于将内存视图的元素类型改变为其他类型,这对于处理数据的二进制表示特别有用。通过 cast(),你可以将一个字节序列或数组解释为另一种数据类型(例如将字节数据解释为 int 或 float 类型的数组),而不需要实际拷贝内存数据。
语法:
memoryview.cast(format)
format:表示目标数据类型的字符串。它是一个格式字符,遵循 Python 的struct模块的格式字符串规则,通常是用于表示 C 语言中的数据类型,如'B'(无符号字节)、'H'(无符号短整型)、'I'(无符号整型)、'f'(浮点数)等。
返回值:
- 返回一个新的
memoryview对象,该对象以新的数据类型(由format指定)来解释原始数据。
常见的 format 字符:
'B':无符号字节(0–255)'H':无符号短整型(0–65535)'I':无符号整型(0–4294967295)'f':32 位浮点数'd':64 位浮点数
示例:使用 cast() 转换数据类型
示例 1:将字节数据转换为整数数组
# 原始字节数据
data = bytearray(b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00')
# 创建 memoryview
mv = memoryview(data)
# 使用 cast() 将字节数据解释为无符号整数(4 字节)
mv_int = mv.cast('I') # 4 字节无符号整数('I')
print(list(mv_int)) # 输出: [1, 2, 3]
- 在这个例子中,原始数据是
bytearray,它包含了四个字节的数据。我们通过cast('I')将这些字节解释为无符号的 4 字节整数数组,结果是[1, 2, 3]。
示例 2:将字节数据转换为浮点数数组
# 原始字节数据(4字节每个元素)
data = bytearray(b'\x00\x00\x80\x3f\x00\x00\x00\x40')
# 创建 memoryview
mv = memoryview(data)
# 使用 cast() 将字节数据解释为浮点数(4字节)
mv_float = mv.cast('f') # 4 字节浮点数('f')
print(list(mv_float)) # 输出: [1.0, 2.0]
- 这里,我们将字节数据转换为浮点数,每 4 个字节解释为一个浮点数。
b'\x00\x00\x80\x3f'对应于浮点数1.0,b'\x00\x00\x00\x40'对应于2.0。
cast() 的优势
- 内存共享:cast() 方法不会复制数据,它返回的 memoryview 只是对原始数据的一个新视图,重新解释数据的格式。这样,你可以在不创建副本的情况下查看数据的不同类型表示。
- 高效:对于大型数据集,cast() 可以避免数据的复制,并且允许以不同的方式访问和修改内存中的内容。
- 适用场景:cast() 对于需要高效处理二进制数据的场景特别有用,比如图像处理、文件解析、网络数据处理等。
使用场景
- 处理二进制协议:在处理二进制数据协议时,你可能需要将字节数据按不同的类型进行解析,cast() 可以高效地实现这一点。
- 与 NumPy 配合使用:memoryview 可以与 NumPy 数组结合使用,cast() 可以将字节流解释为 NumPy 数组中的其他数据类型。例如,你可以将原始字节数据视为整数数组、浮点数组等。
- 数据转换:cast() 在需要将字节数据视为不同数据类型(如将字节数据解释为整数、浮点数等)时非常有用。
总结
cast()是memoryview对象的方法,用于将内存视图的数据类型进行转换。它非常高效,因为它不需要复制数据,只是通过不同的方式解释内存中的数据。- 常见用途:它在处理二进制数据、文件操作、图像处理和科学计算等场景中非常有用,特别是在需要高效处理大数据时。
评论(0)