PyO3 Class 详解 - 在 Python 中使用 Rust 类

PyO3 Class 详解 - 在 Python 中使用 Rust 类

PyO3 是一个强大的库,允许我们在 Rust 中定义类并在 Python 中使用。本文将详细介绍 PyO3 类的各种特性和使用方法。


📌 基本概念

PyO3 允许定义原生 Rust 类型并在 Python 中将其作为类公开。

定义类的基本语法

rust 复制代码
use pyo3::prelude::*;

#[pyclass]
struct MyClass {
    num: i32,
    debug_buffer: String,
}

🔧 构造函数

默认情况下,#[pyclass] 类型只能从 Rust 代码实例化。要使其可从 Python 实例化,需添加构造函数。

自定义构造函数

rust 复制代码
#[pymethods]
impl MyClass {
    #[new]
    fn new(num: i32) -> Self {
        MyClass { num }
    }
}

🎯 获取 Python 对象

当函数返回 #[pyclass] 类型时,会自动转换为 Python 对象。

使用 PyRef 和 PyRefMut

rust 复制代码
#[pymethods]
impl MyClass {
    // 只读访问
    fn get_debug_buffer(slf: PyRef<Self>) -> PyRef<String> {
        PyRef::map(slf, |this| &this.debug_buffer)
    }

    // 可变访问
    fn append_to_debug_buffer(mut slf: PyRefMut<Self>, value: String) -> PyResult<()> {
        slf.debug_buffer.push_str(&value);
        Ok(())
    }
}

💀 析构函数

rust 复制代码
#[pymethods]
impl MyClass {
    fn __del__(&self) {
        println!("MyClass is being deallocated");
    }
}

👪 继承

通过 extends 参数让 Rust 类继承其他 Python 类:

rust 复制代码
#[pyclass(extends=PyException)]
struct MyError {
    #[pyo3(get, set)]
    value: i32,
}

#[pymethods]
impl MyError {
    #[new]
    fn new(value: i32) -> (Self, PyException) {
        (MyError { value }, PyException::new_err("Error occurred"))
    }
}

⚙️ 配置参数

#[pyclass] 支持多种配置选项:

  • name: 指定 Python 中的类名
  • freelist: 优化内存分配
  • weakref: 启用弱引用支持
  • unsendable: 标记为非线程安全
  • module: 指定所属模块
rust 复制代码
#[pyclass(name = "MyCustomClass", freelist = 100, weakref, unsendable, module = "mymodule")]
struct MyClass {
    #[pyo3(get, set)]
    num: i32,
}

⚠️ 限制条件

无生命周期参数

  • Rust 生命周期是编译时概念,Python 运行时无法追踪
  • #[pyclass] 不能有生命周期参数

无泛型参数

  • Rust 泛型在每个使用点生成新实现
  • Python 需要单一实现与解释器集成
  • 解决方案:使用宏为每种具体类型生成类
rust 复制代码
macro_rules! create_interface {
    ($name: ident, $type: ty) => {
        #[pyclass]
        pub struct $name {
            inner: GenericClass<$type>,
        }
        #[pymethods]
        impl $name {
            #[new]
            pub fn new(data: $type) -> Self {
                Self {
                    inner: GenericClass { data },
                }
            }
        }
    };
}

create_interface!(IntClass, i64);
create_interface!(FloatClass, f64);

必须线程安全

  • Python 对象可在多线程间共享
  • #[pyclass] 必须实现 SendSync
  • 非线程安全类型可用 unsendable 标记

🔒 内部可变性

Borrow Checking

PyO3 在运行时进行借用检查,类似 std::cell::RefCell<T>

规则

  1. 任何时候只能有一个可变引用或多个不可变引用
  2. 引用不能超出所引用数据的生命周期
  3. Py<T>Bound<'py, T> 在运行时跟踪引用来确保这些规则

📝 字段属性

get/set 属性

rust 复制代码
#[pyclass]
struct MyClass {
    #[pyo3(get, set)]
    num: i32,  // 自动生成 getter 和 setter
    
    #[pyo3(get)]
    readonly_field: String,  // 只读字段
}

✅ 最佳实践

  1. 简单类型默认线程安全 :基础类型如 i32, String 等已满足要求
  2. 避免复杂内部可变性 :谨慎使用 Rc<RefCell<T>> 等非线程安全类型
  3. 合理使用宏:处理泛型限制时使用宏生成具体实现
  4. 明确编码声明:在 Python 文件中声明编码以避免国际化问题

PyO3 提供了一种优雅的方式来在 Rust 和 Python 之间建立互操作性,让我们能够充分利用两种语言的优势。通过掌握这些核心概念,我们可以在项目中有效地使用 PyO3 来构建高性能的 Python 扩展。

📚 更多 PyO3 相关内容,请参考官方文档

相关推荐
小途软件10 小时前
用于机器人电池电量预测的Sarsa强化学习混合集成方法
java·人工智能·pytorch·python·深度学习·语言模型
古城小栈13 小时前
Rust 泛型 敲黑板
rust
古城小栈13 小时前
Rust Trait 敲黑板
开发语言·rust
AI街潜水的八角14 小时前
基于Pytorch深度学习神经网络MNIST手写数字识别系统源码(带界面和手写画板)
pytorch·深度学习·神经网络
大模型真好玩16 小时前
大模型训练全流程实战指南(一)——为什么要学习大模型训练?
人工智能·pytorch·python·大模型·deep learning
纪伊路上盛名在16 小时前
如何为我们的GPU设备选择合适的CUDA版本和Torch版本?
pytorch·深度学习·torch·cuda·英伟达
小途软件16 小时前
ssm327校园二手交易平台的设计与实现+vue
java·人工智能·pytorch·python·深度学习·语言模型
浪客川18 小时前
【百例RUST - 005】所有权和切片
开发语言·后端·rust
古城小栈18 小时前
Axum: Rust 好用的 Web 框架
开发语言·rust
古城小栈19 小时前
Rust 并发、异步,碾碎它们
开发语言·后端·rust