PyO3类绑定实战#pyclass和#pymethods构建Python对象的10个关键技巧【免费下载链接】pyo3Rust bindings for the Python interpreter项目地址: https://gitcode.com/gh_mirrors/py/pyo3在 Python 与 Rust 的集成方案中PyO3是最主流的 Rust bindingsRust 绑定库。本文带你用#[pyclass]和#[pymethods]这两个核心属性快速把 Rust 结构体变成真正的 Python 对象——掌握这 10 个关键技巧你写出的类既安全又好用。先看最终效果——用 Rust 写的类在 Python 里是这样用的from my_module import Counter c Counter(10) c.step(3) print(c) # Counter(13) print(c.value) # 13下面 10 个技巧全部围绕这条主线展开代码均摘自官方指南 guide/src/class.md。技巧 1用 #[pyclass] 把 Rust 结构体变成 Python 类一切从结构体上的一行属性开始#[pyclass] struct Counter { value: i32, step: i32, }PyO3 会自动为它生成 Python 类型并且不能有三类东西生命周期参数、泛型参数、非线程安全类型必须Send Sync。想改名或改命名风格直接在属性里加参数#[pyclass(name Count, rename_all camelCase)]完整参数说明见 pyclass 参数速查表。技巧 2用 #[new] 定义构造函数默认情况下 Python 端无法实例化你的类。在#[pymethods]块里用#[new]标注一个方法即可它对应 Python 的__new__#[pymethods] impl Counter { #[new] fn new(value: i32) - Self { Self { value, step: 1 } } }两个实用细节见 guide/src/class.md构造函数可能失败时返回PyResultSelf即可抛出 Python 异常函数名可以随便起不必叫new。技巧 3用 #[pymethods] 暴露实例方法Rust 的impl块套上#[pymethods]里面的方法就自动变成 Python 方法#[pymethods] impl Counter { fn value(self) - i32 { self.value } fn step(mut self, amount: i32) { self.value amount; } }self表示只读mut self表示可修改字段方法签名里加一个py: Python_参数就能在方法内调用 Python APIPython 侧看不到这个参数同一结构体默认只能有一个#[pymethods]块开启multiple-pymethods特性后可多个。技巧 4两种风格的属性Property字段级快捷方式简单字段直接在#[pyclass]里标注#[pyclass] struct Point { #[pyo3(get, set)] x: i32, #[pyo3(get)] y: i32, }get只读、set可写、get, set读写用name xxx还能让属性名与字段名不同。方法级描述符需要校验或副作用时用#[getter]/#[setter]/#[deleter]#[pymethods] impl Point { #[setter] fn set_x(mut self, value: i32) { self.x value; } }函数名带get_/set_前缀时属性名会自动去掉前缀point.x即可访问。技巧 5实现魔术方法支持 Python 协议__repr__、__eq__、__len__、__getitem__这类魔术方法直接在#[pymethods]里定义同名函数PyO3 会自动放进正确的槽位#[pymethods] impl Counter { fn __repr__(self) - String { format!(Counter({}), self.value) } }更省事的做法是给#[pyclass]加开关参数#[pyclass(str)]基于Display实现自动生成__str__#[pyclass(eq, eq_int)]自动生成比较方法richcmp、add、getitem等同理。全部支持的协议清单见 guide/src/class/protocols.md。技巧 6类方法与静态方法#[classmethod] 与 #[staticmethod]Python 的classmethod、staticmethod和类变量在 PyO3 里各有一个对应属性#[pymethods] impl Counter { #[classmethod] fn from_step(cls: Bound_, PyType, step: i32) - PyResultSelf { ... } #[staticmethod] fn version() - static str { 1.0 } #[classattr] const MAX_VALUE: i32 1024; }小技巧#[new]可以叠加在#[classmethod]上构造出接收类本身的构造函数——继承场景下非常实用。技巧 7用 extends 实现继承包括继承原生类型extends参数让 Rust 类继承另一个 PyO3 类甚至 Python 原生类型如PyDict#[pyclass(extends PyDict)] struct MyDict { private: i32 }继承时构造函数要返回PyClassInitializer并用add_subclass(...)把子类数据挂进去。子类内部用self_.as_super()访问父类。想让 Python 代码也能继续继承你的类记得加subclass参数。技巧 8改名策略name 与 rename_allRust 用snake_casePython 惯例是CamelCase。两个参数让命名各得其所#[pyclass(name MyCounter, rename_all camelCase)] struct my_counter { ... } // Python 侧看到 MyCounter 和 camelCase 方法名另外可用module xxx参数控制类在 Python 中的所属模块名影响__module__和错误信息的展示。技巧 9用 signature 控制参数与默认值#[pyo3(signature ...)]让方法拥有 Python 风格的参数体验默认值、*args、**kwargs#[pymethods] impl Counter { #[new] #[pyo3(signature (value0, step1))] fn new(value: i32, step: i32) - Self { Self { value, step } } }这样Counter()不带参数也能实例化。配合text_signature还能自定义help()中显示的签名文本。完整规则见 guide/src/function/signature.md。技巧 10线程安全与 frozen选对可变性策略Python 对象会在多个线程间自由共享PyO3 默认对类字段做运行时借用检查类似RefCell同一时刻要么多个self要么一个mut self。如果你的类自己用Mutex/AtomicUsize管理可变性就不需要这套检查——声明frozen#[pyclass(frozen)] struct AtomicCounter { value: AtomicUsize, }frozenSync的类甚至可以不持Python令牌直接读写字段性能更好。策略选择详见 guide/src/class/thread-safety.md。小结一张图记住 10 个技巧#技巧对应属性/参数1定义 Python 类#[pyclass]2构造函数#[new]3实例方法#[pymethods]4属性#[pyo3(get, set)]/#[getter]5魔术方法__repr__等 str/eq参数6类/静态方法#[classmethod]/#[staticmethod]/#[classattr]7继承extendsPyClassInitializer8命名name/rename_all/module9参数签名#[pyo3(signature ...)]10可变性frozen延伸阅读类绑定完整章节guide/src/class.md魔术方法与协议清单guide/src/class/protocols.md线程安全讨论guide/src/class/thread-safety.md#[pyclass]全部参数guide/pyclass-parameters.md方法签名规则guide/src/function/signature.md可运行的完整示例examples/maturin-starter/把这 10 个技巧组合起来你写出的 Rust 类在 Python 里就是一个原装对象能被print、能比较、能继承、能被当作参数传递。动手试试吧【免费下载链接】pyo3Rust bindings for the Python interpreter项目地址: https://gitcode.com/gh_mirrors/py/pyo3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考