
PyO3 协议定制指南用20个魔术方法让Rust类成为原生Python对象【免费下载链接】pyo3Rust bindings for the Python interpreter项目地址: https://gitcode.com/gh_mirrors/py/pyo3PyO3是 Rust 调用 Python 解释器的官方绑定库。通过它你可以在#[pymethods]中实现__init__、__str__、__len__、__add__等20 个魔术方法dunder methods让你的 Rust 结构体在 Python 眼里与list、dict、int一样原生——支持print、len()、比较运算、下标访问甚至直接当函数调用。为什么需要定制协议Python 的魔法全部来自数据模型当你写len(x)时解释器实际调用的是x.__len__()print(x)调用x.__str__()x y调用x.__add__(y)。一个刚导出到 Python 的 Rust 类默认只能被创建和调用普通方法打印出来是生硬的builtins.Number object at 0x7f...。而 PyO3 的设计目标是每个 Python 魔术方法都能在#[pymethods]中照写照用PyO3 会自动把它挂到 C 层的正确类型槽slot上性能与纯 C 扩展一致。 完整的协议清单见官方指南guide/src/class/protocols.md一分钟上手构造器与普通方法的写法差异先记住两条特殊规则Python 写法PyO3 写法def __init__(...)用#[new]属性标记的fn new(...)def __str__(...)等其他魔术方法函数名直接写__str__放在#[pymethods]块里#[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] // 替代 __init__ fn new(value: i32) - Self { Self(value) } fn __str__(self) - String { self.0.to_string() } }这就是最小可用形态Python 里str(Number(5))将输出5。20 魔术方法速查表按协议分类 这是全文最实用的一节建议收藏。PyO3 自动处理的主要协议如下协议类别关键魔术方法Python 中生效的语法️ 基础对象__str____repr____hash____bool____call____getattr__str(x)hash(x)bool(x)x()⚖️ 比较__lt____le____eq____ne____gt____ge____richcmp__! 迭代__iter____next____await____aiter____anext__for x in itasync for 容器__len____getitem____setitem____delitem____contains____concat____repeat__len(x)x[0]x[0]11 in xx * 3 数值__add____sub____mul____truediv____mod____pow__及r*/i*变体、__neg____abs____int____float__-*/%**int(x)float(x) 垃圾回收__traverse____clear__由 Python GC 自动触发完整签名与返回值约束在 guide/src/class/protocols.md 中逐一列出。手把手5 步定制你的第一个原生Rust 类第 1 步字符串表示 ——__repr__与__str____repr__面向开发者理想状态下应能复现该对象如Number(5)__str__面向用户的友好输出如5。偷懒技巧如果 Rust 类型实现了Display只需一行注解即可自动生成__str__#[pyclass(str)] // 自动用 Display 生成 __str__ struct Coordinate { x: i32, y: i32, z: i32 }对结构体还有更短的写法#[pyclass(str ({x}, {y}, {z}))]直接写格式串见 guide/src/class/object.md。第 2 步比较运算 —— 一个__richcmp__搞定 6 个操作符逐个实现__lt__、__gt__太啰嗦PyO3 支持用__richcmp__一次覆盖全部比较fn __richcmp__(self, other: Self, op: CompareOp) - bool { op.matches(self.0.cmp(other.0)) // 用 Rust 的 Ord 一行搞定 }⚠️两个必知陷阱详见 guide/src/class/object.md实现任意比较方法后Python 会不再自动生成默认__hash__你的类将不可哈希——请同时实现__hash____richcmp__不能与__lt__等 6 个细粒度方法混用。 更懒的技巧#[pyclass(frozen, eq, hash)] Rust 的derive(PartialEq, Hash)可自动生成__eq__与__hash__。第 3 步让len()和in工作 —— 容器协议fn __len__(self) - usize { self.vec.len() } fn __contains__(self, item: Bound_, PyAny) - PyResultbool { /* ... */ } fn __getitem__(self, key: Bound_, PyAny) - PyResultPyObject { /* ... */ }进阶细节这是新手最容易踩的坑PyO3 默认会同时填充 mapping 槽和 sequence 槽。dict这类映射型类建议加#[pyclass(mapping)]否则会意外获得基于下标的默认__iter__想让numpy等库把你的类识别为序列用#[pyclass(sequence)]它还会自动处理负数下标。真实项目中支持整数下标 切片的完整实现可参考示例 examples/getitem/src/lib.rs。第 4 步可迭代 ——__iter__与__next__让类支持for x in obj只需两个方法__iter__返回迭代器__next__返回Option值——返回None即表示迭代结束等价于 Python 抛StopIteration。fn __iter__(slf: PyRef_, Self) - PyRef_, Self { slf } fn __next__(mut slf: PyRefMut_, Self) - Optionusize { slf.inner.next() }第 5 步可调用 —— 让实例像函数一样使用实现__call__后实例可以直接obj()调用参数表与普通方法完全相同。这是实现 Python 装饰器、回调计数器的经典手法完整案例见官方示例 examples/decorator/src/lib.rs 与指南 guide/src/class/call.md。进阶缓冲区协议与垃圾回收集成Buffer 协议实现__getbuffer__/__releasebuffer__后你的类可以被numpy、memoryview直接读取内存是高性能数值库的标配GC 集成当你的 Rust 类持有其他 Python 对象引用时实现__traverse__用visit.call()报告每个引用和__clear__断开可变引用参与 Python 循环垃圾回收。继承场景下父类的这两个方法会被自动调用无需手动转发。这两个方法对应 C API 的tp_traverse/tp_clear槽位细节见 guide/src/class/protocols.md 的Garbage Collector Integration一节。避坑清单 ⚡常见疑问正确答案能不能写__init__不能PyO3 用#[new]构造器替代能不能写__del__目前不支持析构逻辑写在 Rust 的Drop中比较/算术方法参数类型不匹配会怎样自动生成NotImplementedPython 会尝试反射操作而非报错__hash__返回什么任意 ≤64 位整数类型PyO3 自动转换为isize学习路线与延伸阅读 类与构造器基础guide/src/class.md 基础定制字符串、哈希、比较guide/src/class/object.md 数值协议溢出、包装、wrapping策略guide/src/class/call.md 与 guide/src/class/numeric.md 协议全量清单本文速查表的出处guide/src/class/protocols.md 可运行的下标访问示例examples/getitem/ 一句话总结Rust 负责性能与内存安全Python 协议负责手感。用#[pymethods]里的 20 个魔术方法把两者接起来你的类型就能无缝融入 Python 生态——len()、print、、for、in一切如你所料。【免费下载链接】pyo3Rust bindings for the Python interpreter项目地址: https://gitcode.com/gh_mirrors/py/pyo3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考