如何通过PyO3在Rust中修改Python的自定义Rust对象列表?
解决PyO3中Python自定义对象列表传入Rust函数并修改的问题
错误原因
你遇到的编译错误是因为PyO3未为Vec<&ListElement>实现FromPyObject trait。Python中的自定义pyclass对象会被PyO3用PyCell包裹,以此兼容Python的引用模型和可变借用规则,直接使用&ListElement无法正确映射Python对象的引用关系。
修改后的代码
use pyo3::prelude::*; use pyo3::types::PyList; #[pyclass] pub struct ListElement { pub value_sum: f32 } #[pymethods] impl ListElement { #[new] fn new(value_sum: f32) -> Self { ListElement { value_sum } } fn add_value(&mut self, value: f32) { self.value_sum += value; } } #[pyfunction] fn modify_list_elements(py: Python<'_>, list: &PyList, value: f32) -> PyResult<()> { // 遍历Python列表中的每个元素 for elem in list.iter() { // 将元素提取为PyCell包裹的ListElement let cell = elem.extract::<&PyCell<ListElement>>()?; // 获取可变引用并调用修改方法 cell.borrow_mut().add_value(value); } Ok(()) } #[pymodule] fn my_rust_module(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::<ListElement>()?; m.add_function(wrap_pyfunction!(modify_list_elements, m)?)?; Ok(()) }
关键修改点
- 参数类型调整:将列表参数从
Vec<&ListElement>改为&PyList,直接接收Python原生列表对象,避免类型转换不兼容问题。 - 元素提取与可变借用:通过
elem.extract::<&PyCell<ListElement>>()将列表元素转换为PyCell包裹的对象,再用borrow_mut()获取可变引用,确保符合Rust的借用规则和Python的对象模型。 - 错误处理:函数返回
PyResult<()>,处理元素提取时可能出现的类型不匹配等错误。
你的Cargo.toml配置无需修改,保持原样即可。
内容的提问来源于stack exchange,提问作者rustbegginer
相关产品推荐
相关产品推荐

