You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从PyAny对象属性获取Parent或Child的Rust结构体?

动态获取PyO3中Parent或Child结构体的解决方案

要根据rust_class的实际类型动态提取Parent或Child,可以利用PyO3的类型匹配机制,通过尝试提取子类类型、失败后回退到父类类型的方式实现。以下是具体实现步骤:

修改后的Rust函数代码

use pyo3::{PyAny, PyRef, PyResult, pyfunction};

#[pyclass(subclass)]
struct Parent {
    foo: i32
}

#[pyclass(extends=Parent)]
struct Child {
    bar: i32
}

#[pyfunction]
fn my_function(my_other_class: &PyAny) -> PyResult<i32> {
    // 获取rust_class属性的PyAny实例
    let rust_class = my_other_class.getattr("rust_class")?;

    // 优先尝试提取Child类型
    match rust_class.extract::<PyRef<Child>>() {
        Ok(child_ref) => {
            // 通过as_ref()获取父类Parent的引用
            let parent_ref = child_ref.as_ref();
            // 返回子类和父类字段的组合值(示例逻辑)
            Ok(parent_ref.foo + child_ref.bar)
        }
        Err(_) => {
            // 提取失败则尝试提取Parent类型
            let parent_ref = rust_class.extract::<PyRef<Parent>>()?;
            Ok(parent_ref.foo)
        }
    }
}

关键说明

  • 使用PyRef<T>类型:直接提取结构体(如Child或Parent)仅适用于非继承场景,继承类需要用PyRef<T>来持有Python对象的不可变引用(可变场景用PyRefMut<T>)。
  • 类型匹配逻辑:先尝试提取子类Child,因为父类Parent的实例无法被提取为Child,失败后再提取Parent,确保覆盖所有合法类型。
  • 访问父类字段:对于Child的引用,通过as_ref()方法可以获取其继承的Parent实例引用,从而访问父类的foo字段;同时可直接访问子类的bar字段。

另一种实现方式(使用downcast)

也可以通过downcast方法直接判断Python对象的类型:

#[pyfunction]
fn my_function(my_other_class: &PyAny) -> PyResult<i32> {
    let rust_class = my_other_class.getattr("rust_class")?;

    if let Ok(child_cell) = rust_class.downcast::<pyo3::PyCell<Child>>() {
        let child = child_cell.borrow();
        let parent = child.as_ref();
        Ok(parent.foo + child.bar)
    } else if let Ok(parent_cell) = rust_class.downcast::<pyo3::PyCell<Parent>>() {
        let parent = parent_cell.borrow();
        Ok(parent.foo)
    } else {
        Err(pyo3::exceptions::PyTypeError::new_err("rust_class must be Parent or Child instance"))
    }
}

这种方式更直接,通过downcast判断对象的实际类型,再分别处理。

内容的提问来源于stack exchange,提问作者Darren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 20:44:59