memoryview()函数是一个内置函数,它返回一个memoryview对象,该对象可以用于在 Python 中访问二进制数据。
函数语法
memoryview(obj)
参数:
obj:支持缓冲协议的对象,例如bytes、bytearray、array.array等;
返回的memoryview对象提供了一个类似于bytearray对象的接口,但它不是一个真正的可变序列,而是一个只读视图,它可以访问原始对象的内存。
在操作二进制数据时,例如音频、视频或图像文件,使用memoryview()函数可以提高处理效率,因为它允许您直接访问原始数据的内存,而无需创建临时副本。
memoryview() 函数示例
以下是一些简单的示例,演示如何使用memoryview()函数访问二进制数据:
# 创建一个包含二进制数据的 bytes 对象
data = bytes([0x10, 0x20, 0x30, 0x40])
# 创建一个内存视图对象
view = memoryview(data)
# 访问内存视图对象的内容
print(view[0]) # 输出 16
print(view[1]) # 输出 32
print(view[2]) # 输出 48
print(view[3]) # 输出 64
view2 = memoryview(b'abcefg')
print(view2[0]) # 输出 97
print(view2[1]) # 输出 98
# 使用切片访问
print(view2[1:4]) # 输出 <memory at 0x0000021D34B9E7C0>
如果下层对象是可写的,则memoryview支持一维切片赋值,改变大小则不被允许:
data = bytearray(b'abcefg')
view = memoryview(data)
print(view.readonly)
view[0] = ord(b'z')
view[1:3] = b'xx'
#view[1:3] = b'kkk' #不被允许,长度不匹配
print(data)
程序运行结果
False bytearray(b'zxxefg')
memoryview 的性能
与切片访问的不同:
# 传统方式:切片会创建新的数据副本
data = bytearray(b'Hello World')
slice1 = data[0:5] # 创建了新的字节数组副本
slice1[0] = 90 # 只修改副本,不影响原数据
# 使用 memoryview:零复制访问
mv = memoryview(data)
slice2 = mv[0:5] # 不复制数据,直接访问原数据缓冲区
slice2[0] = 90 # 直接修改原数据
print(data) # bytearray(b'Zello World')
memoryview 对象
memoryview提供一些常用方法和属性:
.tobytes() 方法
将缓冲区中的数据作为字节串返回。这相当于在memoryview上调用bytes构造器:
view = memoryview(b'abcdefg')
print(view.tobytes()) # 输出 b'abcdefg'
print(bytes(view)) # 输出 b'abcdefg'
.hex() 方法
返回一个字符串对象,其中分别以两个十六进制数码表示缓冲区里的每个字节:
view = memoryview(b'abcdefg')
print(view.hex()) # 输出 61626364656667
.tolist() 方法
将缓冲区内的数据以一个元素列表的形式返回:
view = memoryview(b'abcdefg')
print(view.tolist()) #输出 [97, 98, 99, 100, 101, 102, 103]
.toreadonly() 方法
返回memoryview对象的只读版本。原始的memoryview对象不会被改变:
view = memoryview(b'abcdefg')
view2 = view.toreadonly()
view2[1:3] = b'xx' # TypeError: cannot modify read-only memory
.release() 方法
释放memoryview对象的底层缓冲区:
view = memoryview(b'abcdefg')
view.release()
print(view[0]) #ValueError: operation forbidden on released memoryview object
使用with语句,可以通过上下文管理协议达到类似的效果:
with memoryview(b'abcdefg') as view:
print(view[0]) # 输出 97
print(view[0]) #ValueError: operation forbidden on released memoryview object
readonly属性
是否为只读,取决于下层对象:
v1 = memoryview(bytes(b'abcdefg'))
print(v1.readonly) # True
v2 = memoryview(bytearray(b'abcdefg'))
print(v2.readonly) # False
nbytes属性
获取总字节数:
view = memoryview(bytes(b'abcdefg'))
print(view.nbytes) # 7
itemsize属性
获取每个元素的字节数;