
编程语言语言运行时解释器标准库【免费下载链接】cpythonThe Python programming language项目地址https://gitcode.com/GitHub_Trending/cp/cpython点击查看免费下载memoryview.cast()是 CPython 中用于在不复制底层缓冲区的前提下改变内存视图格式与形状的核心方法。CPython 主分支对应 Doc/whatsnew/3.16.rst在本版本中放宽了它的连续性约束多维N-DFortran 连续F-contiguous视图现在也可以直接转换为 1-D 视图见 Misc/NEWS.d/next/Core_and_Builtins/2025-08-15-06-28-45.gh-issue-91484.huCgHt.rst。本文从该变更出发结合标准库文档、Objects/memoryobject.c源码实现与测试用例完整讲解memoryview.cast的能力边界、源码原理与实战用法读者读完后可以准确判断何时可以使用零拷贝 cast以及如何与列主序column-major数据交互。变更背景cast 曾经的连续性限制memoryview.cast(format, shapeNone, *, orderC)的语义是把现有缓冲区按新的元素格式与形状重新解释核心约束包括返回的是新 memoryview 对象但底层缓冲区绝不复制所有 cast 都是零拷贝的视图操作支持1D - C-contiguous、C-contiguous - 1D以及本版本新增的F-contiguous - 1D见 Doc/builtins/stdtypes.rst目标格式必须是struct语法中的单一原生元素格式且源格式与目标格式中至少有一个是字节格式B、b或c结果视图的字节长度必须与原始缓冲区完全一致。在旧版本中把多维视图降维成 1-D 只允许C 连续的输入一个按 Fortran列主序布局存放的多维视图会直接抛出TypeError: memoryview: casts are restricted to contiguous views。这对科学计算与二进制互操作场景很不友好——许多底层库尤其是 Fortran 编写的数值库输出的数据天然就是列主序的。本次变更由 Jaemin Park 贡献对应 gh-issue-91484正是为了消除这一限制。源码实现剖析约束是如何被放宽的1. 入口处的连续性检查memoryview.cast的 C 实现位于 Objects/memoryobject.c 的memoryview_cast_impl()。入口处最关键的是连续性校验逻辑if (!MV_C_CONTIGUOUS(self-flags)) { if (shape || !MV_F_CONTIGUOUS(self-flags)) { PyErr_SetString(PyExc_TypeError, memoryview: casts are restricted to contiguous views); return NULL; } }这段代码的语义是当输入视图不是 C 连续时——如果调用者同时传了shape即要做 N-D → N-D 的重塑或者输入连 F 连续都不是则直接报TypeError只有当未传 shape即做 N-D → 1-D 的降维且输入是F 连续时才放行。这正是本次 NEWS 条目所描述的casting from N-D to 1-D for F-contiguous在代码层面的落点。也就是说维度变换被严格限定为两种合法路径1D - ND重塑输入必须 C 连续和ND - 1D降维输入必须是 C 或 F 连续。后续代码中还有一条显式断言if (self-view.ndim ! 1 ndim ! 1) { PyErr_SetString(PyExc_TypeError, memoryview: cast must be 1D - ND or ND - 1D); return NULL; }此外入口处还校验了order只能是字符串C或F否则抛ValueError: order must be C or Fshape 的维数不能超过PyBUF_MAX_NDIM64定义于 Include/pybuffer.h形状中不允许出现 0zero_in_shape()检查否则抛TypeError: cannot cast view with zeros in shape or strides。2. 两步式 cast 内部流程memoryview_cast_impl()的处理分两步分别对应两个内部函数第一步cast_to_1D()Objects/memoryobject.c把整个视图按新格式展平为 1-D通过get_native_fmtchar()解析目标格式必须是可选的前缀加原生格式字符校验至少一个格式为字节格式IS_BYTE_FORMAT否则抛TypeError: cannot cast between two non-byte formats校验view-len % itemsize 0字节总长必须是新元素大小的整数倍重设ndim 1、shape[0] len / itemsize、strides[0] itemsize并清空suboffsets。第二步cast_to_ND()Objects/memoryobject.c仅在提供了shape时执行把第一步得到的 1-D 视图重塑为指定维数通过copy_shape()逐个解析 shape 元素必须为正整数且product(shape) * itemsize不得超过PY_SSIZE_T_MAX按order选择步长初始化方式order F走init_fortran_strides_from_shape()Objects/memoryobject.c否则走init_strides_from_shape()Objects/memoryobject.c最终校验view-len product(shape) * itemsize否则抛TypeError: product(shape) * itemsize ! buffer size。两个初始化步长数组的函数分别实现行主序与列主序的步长递推/* C-contiguous: strides[last] itemsize向前依次累乘 */ view-strides[view-ndim-1] view-itemsize; for (i view-ndim-2; i 0; i--) view-strides[i] view-strides[i1] * view-shape[i1]; /* F-contiguous: strides[0] itemsize向后依次累乘 */ view-strides[0] view-itemsize; for (i 1; i view-ndim; i) view-strides[i] view-strides[i-1] * view-shape[i-1];最终由init_flags()Objects/memoryobject.c根据新的 ndim、shape、strides 重新计算c_contiguous/f_contiguous标志位。整个过程中Py_buffer的buf指针与len从未改变这正是零拷贝的保证。标准用法与完整示例以下示例全部来自标准库文档 Doc/builtins/stdtypes.rst可以在 Python 3.16 交互式环境中直接复现。示例 11D/long 转为 1D/unsigned bytes import array a array.array(l, [1,2,3]) x memoryview(a) x.format l x.itemsize 8 len(x) 3 x.nbytes 24 y x.cast(B) y.format B y.itemsize 1 len(y) 24 y.nbytes 24三个long元素共 24 字节被重新解释为 24 个无符号字节元素大小从 8 变成 1视图长度同步变为 24字节总数不变。示例 21D/bytes 转 3D/ints 再转回 1D/signed char import struct buf struct.pack(i*12, *list(range(12))) x memoryview(buf) y x.cast(i, shape[2,2,3]) y.tolist() [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] y.format i y.itemsize 4 len(y) 2 y.nbytes 48 z y.cast(b) z.format b z.itemsize 1 len(z) 48 z.nbytes 48这里y是 C 连续默认orderC的 3-D int 视图y.cast(b)正是多维 C 连续 → 1-D的降维路径在旧版本中就已经支持本次变更把同样的降维能力扩展到了 F 连续的输入。示例 31D/unsigned long 转 2D/unsigned long buf struct.pack(L*6, *list(range(6))) x memoryview(buf) y x.cast(L, shape[2,3]) len(y) 2 y.nbytes 48 y.tolist() [[0, 1, 2], [3, 4, 5]]新增的 order 参数零拷贝的列主序视图与 gh-issue-91484 同步进入 3.16 的还有order关键字参数gh-issue-78959见 Doc/whatsnew/3.16.rst。它让1D - ND的重塑可以直接产出 Fortran 连续视图对于对接列主序的数值库非常实用 buf bytes(range(6)) y memoryview(buf).cast(B, shape[3, 2], orderF) y.f_contiguous True y.tolist() [[0, 3], [1, 4], [2, 5]]注意tolist()的输出物理上字节顺序仍是0,1,2,3,4,5但逻辑上按列主序排成了[[0,3],[1,4],[2,5]]。因为视图不复制缓冲区orderF只是改变 strides 的解释方式y.tobytes(A)仍返回原始物理字节。边界条件与错误行为cast的签名是cast(format, /)与cast(format, shape, /, *, orderC)其中order是仅限关键字参数。测试用例 Lib/test/test_memoryview.py 的test_cast_order系统地验证了这些边界# order 仅限关键字位置传参会抛 TypeError self.assertRaises(TypeError, mv.cast, B, (3, 2), F) # order 只能是 C 或 F self.assertRaises(TypeError, mv.cast, B, shape(3, 2), orderNone) self.assertRaises(ValueError, mv.cast, B, shape(3, 2), orderX) self.assertRaises(ValueError, mv.cast, B, shape(3, 2), orderA)同一测试还验证了 strides 的数值结果c mv.cast(B, shape(3, 2)) # 默认 C 连续 assert c.strides (2, 1) # 行主序 f mv.cast(B, shape(3, 2), orderF) # F 连续 assert f.strides (1, 3) # 列主序 # 零拷贝验证物理字节不变 assert f.tobytes(A) bytes(range(6))test_cast_order_writableLib/test/test_memoryview.py进一步证明 F 连续视图与原始缓冲区共享内存b bytearray(6) f memoryview(b).cast(B, shape(3, 2), orderF) f[0, 1] 9 # 列主序下 (0,1) 的物理偏移是 1*33 assert b[3] 9 # 写回成功二者是同一块内存组合使用完整的工作流把 3.16 的两项增强F 连续 N-D→1-D 降维 order 参数组合起来可以构建一个完整的零拷贝数据通路从列主序底层缓冲区构造 F 连续视图 → 降维为 1-D → 按 C 顺序重塑或直接导出字节import array, struct # 模拟一个列主序存放的 2x3 数组物理字节仍为 0..5 buf bytearray(range(6)) fview memoryview(buf).cast(B, shape(3, 2), orderF) # 新能力F 连续 N-D 视图直接降维为 1-D全程零拷贝 flat fview.cast(B) print(flat.tolist()) # [0, 1, 2, 3, 4, 5] # 降维后再按 C 顺序重塑为行主序逻辑视图 cview flat.cast(B, shape(2, 3), orderC) print(cview.tolist()) # [[0, 1, 2], [3, 4, 5]]需要说明的是旧版本中 F 连续 N-D 视图降维会被拒绝TypeError: casts are restricted to contiguous views现在则完全合法而1D - ND重塑仍要求输入必须是 C 连续——这是源码中保留的对称约束。适用前提与限制本文所述行为对应当前 CPython 主分支Python 3.16见 Doc/whatsnew/3.16.rst以及 Doc/builtins/stdtypes.rst 中标注versionchanged:: next的部分旧版本如 3.15 及更早不具备 F 连续 N-D→1-D 降维与order参数能力所有 cast 均要求输入视图连续C 或 F非连续视图如切片后的m[::2]无法 cast字节长度itemsize可能随操作系统不同而变化如l、L、n、N跨平台代码不要硬编码元素大小目标格式必须是单一原生元素格式且源、目标格式至少一方为字节格式本文章节中的代码示例与错误行为均可通过仓库内测试 Lib/test/test_memoryview.py 与源码 Objects/memoryobject.c 验证读者可按需深入研读。赞分享编程语言语言运行时解释器标准库【免费下载链接】cpythonThe Python programming language项目地址https://gitcode.com/GitHub_Trending/cp/cpython点击查看免费下载相关推荐SciPy 1.16.0 版本特性全解析数组 API 支持、COBYLA 重写与 n-D 批处理能力SciPy 1.16.0 版本特性全解析数组 API 支持、COBYLA 重写与 n D 批处理能力 SciPy 1.16.0 是历经 6 个月开发的重要版本科学计算数据科学高性能计算Modin 的 pandas 实用函数支持矩阵从 Y/N/P/D 到源码实现解析Modin 的 pandas 实用函数支持矩阵从 Y/N/P/D 到源码实现解析 本指南以 Modin 官方支持矩阵文档 docs/supported_api数据分析数据工程大数据Short Video Factory一键生成AI营销短视频的终极解决方案Short Video Factory一键生成AI营销短视频的终极解决方案 在当今数字营销时代短视频已成为产品推广和内容创作的核心载体。然而制作高质量的短人工智能AI 应用桌面应用音视频媒体生成语音AI 写作上一篇npm workspaces vs pnpm vs Lerna从 sample-monorepo 看 monorepo 工具链怎么选下一篇smallnest/rpcx性能调优案例某支付系统的优化实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考