|
PyDictは、pyo3でPythonのdict(ディクショナリー)(Rust的にはHashMap)を表す型。
PyDictを操作するメソッドはPyDictMethodsトレイトで定義されている。
use pyo3::types::PyDict; use pyo3::types::PyDictMethods;
PyO3 0.27では、PythonのdictをBound<PyDict>で受け取る。
use pyo3::{prelude::*, types::*};
#[pyfunction]
fn my_dict(dict: &Bound<PyDict>) -> PyResult<String> {
println!("my_dict.len={}", dict.len());
let mut s = String::new();
for (key, value) in dict.iter() {
let key: &str = key.extract()?;
s.push_str(key);
s.push_str("=");
if value.is_instance_of::<PyString>() {
let value: &str = value.extract()?;
s.push_str(value);
} else if value.is_instance_of::<PyInt>() {
let value: i64 = value.extract()?;
s.push_str(&value.to_string());
} else {
s.push_str("unknown-type");
};
s.push_str(", ");
}
Ok(s)
}
dict.iter()で取れるkey・valueはBound<PyAny>型なので、is_instance_ofメソッドで具体的な型を判定し、extractメソッドで変換する。
print(example_pyo3.my_dict({"key1":"value1", "key2": 123, "key3": 123.4}))
dictの値の型が固定なのであれば、引数に直接HashMapを指定できる。
#[pyfunction]
fn my_dict(dict: HashMap<String, String>) -> PyResult<String> {
println!("{:?}", dict);
let mut s = String::new();
for (key, value) in dict.iter() {
s.push_str(key);
s.push_str("=");
s.push_str(value);
s.push_str(", ");
}
Ok(s)
}
この例ではHashMapのキーと値の型がStringなので、呼び出すPython側で文字列以外を指定すると、実行時にエラーが発生する。
Pythonの関数の**kwargsを受け取るには、PyO3 0.27ではシグネチャーを定義する。
use pyo3::{prelude::*, types::*};
#[pyfunction]
#[pyo3(signature = (arg1, **kwargs))]
fn my_kwargs(py: Python, arg1: String, kwargs: Option<Bound<PyDict>>) -> PyResult<String> {
let mut s = arg1.clone();
s.push_str("--");
if let Some(dict) = kwargs {
for (key, value) in dict.iter() {
let key: &str = key.extract()?;
s.push_str(key);
s.push_str("=");
if value.is_instance_of::<PyString>() {
s.push_str(value.extract::<&str>()?);
} else if value.is_instance_of::<PyInt>() {
s.push_str(&value.extract::<i64>()?.to_string());
} else {
s.push_str("unsupported-type");
}
s.push_str(", ");
}
}
Ok(s)
}
print(example_pyo3.my_kwargs("abc"))
print(example_pyo3.my_kwargs("abc", key1="def", key2="ghi"))