|
PyAnyは、pyo3でPythonのオブジェクトを表す型。
use pyo3::types::PyAny;
ちなみに、PyObjectはPy<PyAny>だが、pyo3 0.26.0で非推奨になったらしい。
(直接Py<PyAny>を使えということらしい>)
PyAnyがPythonで具体的にどんな型だったのかは、is_instance_ofメソッドで判定できる。
use pyo3::{prelude::*, types::*};
#[pyfunction]
fn my_type(value: Bound<PyAny>) -> PyResult<&str> {
let r = if value.is_instance_of::<PyString>() {
"PyString"
} else if value.is_instance_of::<PyInt>() {
"PyInt"
} else if value.is_instance_of::<PyFloat>() {
"PyFloat"
} else {
"unknown-type"
};
Ok(r)
}
PyAnyから具体的な型へは、extractメソッドで変換できる。
use pyo3::{prelude::*, types::*};
#[pyfunction]
fn my_extract(value: Bound<PyAny>) -> PyResult<String> {
let r = if value.is_instance_of::<PyString>() {
let value: &str = value.extract()?;
format!("PyString: {}", value)
} else if value.is_instance_of::<PyInt>() {
let value: i64 = value.extract()?;
format!("PyInt: {}", value)
} else if value.is_instance_of::<PyFloat>() {
let value: f64 = value.extract()?;
format!("PyFloat: {}", value)
} else {
"unknown-type".to_string()
};
Ok(r)
}
Rustの型からPyAnyへ変換するには、一旦Bound<T>に変換する。[2025-12-20]
#[pymodule]
mod example_pyo3 {
use pyo3::{prelude::*, types::*};
#[pyfunction]
fn return_example(py: Python, arg1: Option<i32>, arg2: Option<&str>) -> PyResult<Py<PyAny>> {
if let Some(n) = arg1 {
let n = n.into_pyobject(py)?; // Bound<PyInt>
let n = n.into_any(); // Bound<PyAny>
return Ok(n.unbind());
}
if let Some(s) = arg2 {
let s = s.into_pyobject(py)?; // Bound<PyString>
let s = s.into_any(); // Bound<PyAny>
return Ok(s.unbind());
}
Ok(py.None())
}
}
または
#[pyfunction]
fn return_example(py: Python, arg1: Option<i32>, arg2: Option<&str>) -> PyResult<Py<PyAny>> {
if let Some(n) = arg1 {
let n = n.into_pyobject(py)?; // Bound<PyInt>
return Ok(n.into());
}
if let Some(s) = arg2 {
let s = s.into_pyobject(py)?; // Bound<PyString>
return Ok(s.into());
}
Ok(py.None())
}
または
#[pyfunction]
fn return_example<'py>(py: Python<'py>, arg1: Option<i32>, arg2: Option<&str>) -> PyResult<Bound<'py, PyAny>> {
// fn return_example(py: Python, arg1: Option<i32>, arg2: Option<String>) -> PyResult<Bound<PyAny>> {
if let Some(n) = arg1 {
let n = n.into_pyobject(py)?; // Bound<PyInt>
return Ok(n.into_any());
// return Ok(n.as_any().clone()); // n.as_any(): &Bound<PyAny>
}
if let Some(s) = arg2 {
let s = s.into_pyobject(py)?; // Bound<PyString>
return Ok(s.into_any());
// return Ok(s.as_any().clone()); // s.as_any(): &Bound<PyAny>
}
Ok(py.None().into_bound(py))
// Ok(py.None().bind(py).clone()) // py.None().bind(py): &Bound<PyAny>
}
> uv run python >>> import example_pyo3 >>> print(example_pyo3.return_example(None, None)) None >>> example_pyo3.return_example(None, "abc") 'abc' >>> example_pyo3.return_example(123, "abc") 123 >>> example_pyo3.return_example(None, None) is None True >>> isinstance(example_pyo3.return_example(None, "abc"), str) True >>> isinstance(example_pyo3.return_example(None, "abc"), int) False >>> isinstance(example_pyo3.return_example(123, "abc"), str) False >>> isinstance(example_pyo3.return_example(123, "abc"), int) True