memoryview 快且省内存的根本原因是绕过数据复制、直接读写原始内存缓冲区;其切片不复制数据,cast() 可零拷贝重解释二进制布局,配合 mmap 能按需访问大文件,但需注意原始缓冲区生命周期。

因为 memoryview 能绕过数据复制,直接读写原始内存缓冲区——这是它快且省内存的根本原因。
memoryview 切片不复制数据,普通 bytes 切片会
当你对 bytes 对象做切片(比如 data[1000:2000]),Python 会立即分配新内存、拷贝对应字节,生成一个全新 bytes 对象。1GB 数据里切 1000 次,就可能额外占用 GB 级内存。
memoryview 切片则不同:它返回一个新的 memoryview 对象,但底层仍指向同一块内存。只要原始对象(如 bytearray)没被释放,所有视图共享物理地址。
- 验证方式:
mv[100:200].obj is original_data返回True - 注意:
bytes创建的memoryview是只读的;要修改必须用bytearray或array.array - 切片后调
bytes()或tolist()才真正触发复制——按需取数,不是默认行为
memoryview.cast() 可零拷贝重解释二进制布局
处理网络包、图像像素或结构化二进制协议时,你常需要把一串字节当作 uint16、float32 或二维数组来读。传统做法是用 struct.unpack() 或 numpy.frombuffer(),它们都要复制数据。
memoryview.cast() 不复制,只改变“怎么看”:
-
mv.cast('H')把字节流当无符号短整型(2 字节/元素)看待 -
mv.cast('B', (256, 256))把一维字节转成 256×256 的灰度图视图 - 修改
cast后的视图,原始bytearray内容同步更新 - 失败条件:原始缓冲区长度必须能被新元素大小整除,否则抛
ValueError
和 mmap 配合使用,可避免加载整个大文件到内存
面对几 GB 的视频或数据库文件,你通常不需要一次性全读进内存。用 mmap 映射文件后,再套一层 memoryview,就能像操作内存一样随机访问任意偏移:
with open('big.bin', 'r+b') as f: mm = mmap.mmap(f.fileno(), 0); mv = memoryview(mm)-
mv[0x10000:0x10010]直接读取文件第 64KB 处的 16 字节,OS 自动按需分页加载 - 写入也生效:
mv[0] = 0xff会写回磁盘对应位置(取决于mmap的access参数) - 关键限制:映射对象(如
mmap实例)必须支持缓冲区协议——它确实支持
真正容易被忽略的是生命周期管理:memoryview 本身不持有数据,但它会强引用原始缓冲区。如果原始 bytearray 被 del 或越出作用域,而你还留着 memoryview,下次访问就会触发 ValueError: underlying buffer is not C-contiguous 或更隐蔽的静默错误。别以为“只是个视图”就不用管它。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











