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

PyO3中如何简化Outer结构体的可迭代实现?无需额外Iter结构体

问题

我定义了如下简单的Rust结构体:

#[pyclass]
struct Outer {
  inner: Vec<i32>
}

根据PyO3文档,要让Outer支持迭代,需要实现__iter__方法,且该方法必须返回一个同时实现__iter__和__next__的类型。文档给出的方案是定义一个Iter结构体:

#[pyclass]
struct Iter {
  iter: std::vec::IntoIter<i32>
}

#[pymethods]
impl Iter {
    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
        slf
    }

    fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<i32> {
        slf.iter.next()
    }
}

随后在Outer中实现__iter__:

#[pymethods]
impl Outer {
    pub fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<Iter>> {
        let iter = Iter {
            iter: slf.inner.clone().into_iter(),
        };
        Py::new(slf.py(), iter)
    }
}

是否存在更简便的实现方式?比如,PyO3可自动将Vec<i32>转换为Python列表,有没有类似捷径,无需实现整个Iter结构体,只需类似如下写法即可完成迭代支持:

fn __iter__(...) {
  self.inner.iter().cloned()
}

同时包裹正确的PyResult等必要处理?我可以接受额外结构体的实现方式,但觉得这一步或许可以省略。

解决方案

确实有更简洁的实现方式,无需手动定义迭代器结构体,以下两种方法都能满足需求:

方法一:复用Python列表的迭代器

既然PyO3可以自动将Vec<i32>转换为Python列表,我们可以直接把inner转成Python列表,再返回它的原生迭代器,让Python自行处理迭代逻辑:

#[pymethods]
impl Outer {
    fn __iter__(slf: PyRef<'_, Self>) -> PyResult<PyObject> {
        let py_list: PyObject = slf.inner.clone().into_py(slf.py());
        py_list.call_method0(slf.py(), "__iter__")
    }
}

这种方式完全依赖Python原生列表的迭代能力,代码量大幅减少,不需要额外定义任何结构体。

方法二:使用PyO3的IntoPyIterator trait

PyO3提供了IntoPyIterator trait,它可以直接将Rust迭代器转换为Python可识别的迭代对象,底层已经封装了__iter__和__next__的实现,完全省去自定义迭代器的步骤,和你期望的写法高度一致:

use pyo3::prelude::*;
use pyo3::iter::IntoPyIterator;

#[pyclass]
struct Outer {
    inner: Vec<i32>
}

#[pymethods]
impl Outer {
    fn __iter__(slf: PyRef<'_, Self>) -> PyResult<impl IntoPyIterator<Item = i32>> {
        Ok(slf.inner.iter().cloned())
    }
}

需要注意的是,只要你的Rust迭代器实现了标准库的Iterator trait,就能通过IntoPyIterator转换为Python迭代对象,而Vec的迭代器天生满足这个条件,所以直接调用cloned()就能得到可转换的迭代器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:20:35