Прохождение Python объекта в ржавчину - PullRequest
1 голос
/ 22 февраля 2020

Я пытаюсь передать объект Python в ржавчину и выполнить операции, используя поля объекта Python.

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)
}   

Ожидаемый результат при вызове с Python будет следующим:

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

Вместо Rust ошибка при компиляции:

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

Есть ли способ перечислить объекты полей и методы в ржавчине и манипулировать полями?

1 Ответ

0 голосов
/ 21 апреля 2020

Вы звоните clone_ref на y:

let y = x.clone_ref(py);

clone_ref возвращает еще PyObject. Затем вы вызываете

y.a += 2;

, и компилятор правильно сообщает вам "нет поля a для типа pyo3 :: PyObject". Поскольку PyObject не предоставляет поля, которые вы ожидаете получить непосредственно в объекте Python (это будет трудно сделать, поскольку python динамически типизируется, тогда как rust является статически типизированным языком, поэтому все члены PyObject должны быть известным во время компиляции). Документация полезна в этих случаях, чтобы узнать, как использовать PyObject. Там вы увидите, что вы все еще можете получить доступ к a, но вам нужно go с помощью метода getattr. Я подозреваю, что для выполнения += лучше всего явно вызвать метод python __iadd__ через call_method API.

...