[英]How can I access a Rust Iterator from Python using PyO3?
I'm quite new with Rust, and my first 'serious' project has involved writing a Python wrapper for a small Rust library using PyO3.我对 Rust 很陌生,我的第一个“严肃”项目涉及使用 PyO3 为小型 Rust 库编写 Python 包装器。 This has mostly been quite painless, but I'm struggling to work out how to expose lazy iterators over Rust Vec
s to Python code.这基本上很轻松,但我正在努力研究如何将 Rust Vec
上的惰性迭代器暴露给 Python 代码。
So far, I have been collecting the values produced by the iterator and returning a list, which obviously isn't the best solution.到目前为止,我一直在收集迭代器产生的值并返回一个列表,这显然不是最好的解决方案。 Here's some code which illustrates my problem:这是一些说明我的问题的代码:
use pyo3::prelude::*;
// The Rust Iterator, from the library I'm wrapping.
pub struct RustIterator<'a> {
position: usize,
view: &'a Vec<isize>
}
impl<'a> Iterator for RustIterator<'a> {
type Item = &'a isize;
fn next(&mut self) -> Option<Self::Item> {
let result = self.view.get(self.position);
if let Some(_) = result { self.position += 1 };
result
}
}
// The Rust struct, from the library I'm wrapping.
struct RustStruct {
v: Vec<isize>
}
impl RustStruct {
fn iter(&self) -> RustIterator {
RustIterator{ position: 0, view: &self.v }
}
}
// The Python wrapper class, which exposes the
// functions of RustStruct in a Python-friendly way.
#[pyclass]
struct PyClass {
rust_struct: RustStruct,
}
#[pymethods]
impl PyClass {
#[new]
fn new(v: Vec<isize>) -> Self {
let rust_struct = RustStruct { v };
Self{ rust_struct }
}
// This is what I'm doing so far, which works
// but doesn't iterate lazily.
fn iter(&self) -> Vec<isize> {
let mut output_v = Vec::new();
for item in self.rust_struct.iter() {
output_v.push(*item);
}
output_v
}
}
I've tried to wrap the RustIterator
class with a Python wrapper, but I can't use PyO3's #[pyclass]
proc.我试图用 Python 包装器包装RustIterator
class,但我不能使用 PyO3 的#[pyclass]
proc。 macro with lifetime parameters.带有生命周期参数的宏。 I looked into pyo3::types::PyIterator
but this looks like a way to access a Python iterator from Rust rather than the other way around.我查看了pyo3::types::PyIterator
但这看起来像是一种从 Rust 访问 Python 迭代器的方法,而不是相反。
How can I access a lazy iterator over RustStruct.v
in Python?如何在RustStruct.v
中通过 RustStruct.v 访问惰性迭代器? It's safe to assume that the type contained in the Vec
always derives Copy
and Clone
, and answers which require some code on the Python end are okay (but less ideal).可以安全地假设Vec
中包含的类型始终派生Copy
和Clone
,并且需要 Python 端的一些代码的答案是可以的(但不太理想)。
You can make your RustIterator
a pyclass
and then implement the proper trait ( PyIterProtocol
) using the rust iter itself.您可以将RustIterator
pyclass
,然后使用 rust 迭代器本身实现适当的特征( PyIterProtocol
)。
Not tested, but something like:未经测试,但类似:
#[pyclass]
pub struct RustIterator<'a> {
position: usize,
view: &'a Vec<isize>
}
impl<'a> Iterator for RustIterator<'a> {
type Item = &'a isize;
fn next(&mut self) -> Option<Self::Item> {
let result = self.view.get(self.position);
if let Some(_) = result { self.position += 1 };
result
}
}
#[pyproto]
impl PyIterProtocol for Iter {
fn __next__(mut slf: PyRefMut<Self>) -> IterNextOutput<usize, &'static str> {
match self.next() {
Some(value) => IterNextOutput::Yield(value),
None => IterNextOutput::Return("Ended")
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.