【问题标题】:Pass List of Python Dictionaries to Rust Function PyO3将 Python 字典列表传递给 Rust 函数 PyO3
【发布时间】:2021-04-10 15:28:13
【问题描述】:

我正在尝试用 rust 编写一个函数,我可以从 python 调用该函数,该函数接受一个字典列表(想想 pandas 类似数据框的数据)并从 rust 访问这些键和值。我怎样才能做到这一点?我正在使用pyo3。我是否需要定义一个与 python dict 输入的键、值对匹配的结构?

作为一个示例函数,我试图传入一个字典列表,并将与键 key 对应的值相加。我的 python 字典列表中的每个字典都有键 key,它对应于一个 int。

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use pyo3::types::PyDict;

#[pyfunction]
fn sum_list_dicts(a: Vec<PyDict>, key: String) -> PyResult<i32> {
    let mut tot = 0_i32;

    for d in a.iter() {
        tot += d[key];
    }
    Ok(tot)
}

#[pymodule]
fn rustpy(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(sum_list_dicts, m)?)?;

    Ok(())
}

【问题讨论】:

    标签: python dictionary rust pyo3


    【解决方案1】:

    所以这真的取决于你真正想要做什么。如果你不想弄乱实际的 Py 项目,你可以简单地这样做:

    #[pyfunction]
    fn sum_list_dicts(a: Vec<HashMap<String, i32>>, key: String) -> PyResult<i32> {
        let mut tot = 0_i32;
    
        for d in a.iter() {
            tot += d[&key];
        }
        Ok(tot)
    }
    

    如果您想使用PyList、PyDict 等,这也可以:

    #[pyfunction]
    fn sum_list_dicts(a: &PyList, key: String) -> PyResult<i32> {
       let mut tot = 0_i32;
    
       for d in a.iter() {
           tot += d.downcast::<PyDict>()?.get_item(&key).unwrap().downcast::<PyInt>()?.extract::<i32>()?;
       }
       Ok(tot)
    }
    

    使用任何一种方法,您都可以简单地从 Python 端调用它:

    a = [{"ham":0, "eggs":0}, {"eggs": 1}, {"eggs": 3, "spam":2}]
    b = sum_list_dicts(a, "eggs")
    print(b)
    >>> 4
    

    【讨论】:

    • 感谢您的回答。只是好奇,PyList/PyDict 是否给我们带来了更多的性能提升,因为与使用 Vec/HashMap 相比,它看起来很冗长
    • 从这些有效地创建 Rust 结构意味着复制所有内容,这可能会更慢。这取决于您的用例,您应该对此进行基准测试。
    猜你喜欢
    • 2015-08-31
    • 1970-01-01
    • 2019-12-12
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多