3

I am trying to pass a Python object into rust and perform operations using the fields of the Python object.

Python:

class myclass(object):
    def __init__(self):
        self.a = 3

b = myclass()
print(b.a)
// 3

Rust:

#[pyfn(m, "rust_obj")]
fn rust_obj_py(py: Python, x: PyObject) -> PyResult<PyObject> { 
    let y = x.clone_ref(py);
    y.a += 2;
    Ok(y)
}   

Expected result when calling from Python would be:

c = rust_obj(b)
print(c.a)
// 5

Instead Rust error out when compiling:

error[E0609]: no field `a` on type `pyo3::PyObject`
   --> src\lib.rs:926:5
    |
926 |         y.a += 2;
    |           ^ unknown field

Is there a way to list the object fields and methods in rust and manipulate the fields?

1 Answer 1

1

You are calling clone_ref on y:

let y = x.clone_ref(py);

clone_ref returns another PyObject. Then you're invoking

y.a += 2;

And the compiler correctly tells you "no field a on type pyo3::PyObject". Because PyObject doesn't expose the fields you would expect in a Python object directly (It would be difficuly to do so since python is dynamically typed whereas rust is a statically typed language, so all members of PyObject have to be known at compile-time). The documentation is helpful in these cases to learn how to use PyObject. There you'll see that you can still access a, but you have to go through the getattr method. In order to do the += I suspect you'd probably best call python's __iadd__ method explicitly through the call_method API.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.