Overriding methods on PyO3 subclasses #4164
-
Hi - I'm new to PyO3, but excited to use it to accelerate some numerical code in Python. I am struggling to understand some aspects of class inheritance. Suppose I have the following Python classes class Animal():
def __init__(self, name):
self.name = name
def _greeting(self) -> str:
return f"Hello, I am a {self.name}"
def speak(self):
print(self._greeting())
class Dog(Animal):
def __init__(self):
super().__init__("dog")
def _greeting(self) -> str:
return f"Woof, woof! I am a {self.name}" Then running this I get dog = Dog()
dog.speak()
# Woof, woof! I am a dog Trying to replicate this in PyO3, I have #[pyclass(subclass)]
struct Animal {
name: String,
}
#[pymethods]
impl Animal {
#[new]
fn new(name: String) -> Self {
Animal { name }
}
fn greeting(&self) -> String {
format!("Hello, I am a {}", self.name)
}
fn speak(&self) {
println!("{}", self.greeting());
}
}
#[pyclass(extends=Animal, subclass)]
struct Dog {}
#[pymethods]
impl Dog {
#[new]
fn new() -> (Self, Animal) {
(Dog {}, Animal::new("dog".to_string()))
}
fn greeting(self_: PyRef<'_, Self>) -> String {
let super_ = self_.as_ref();
format!("Woof, woof! I am a {}", super_.name)
}
} Running this from Python: dog = Dog()
dog.speak()
# Hello, I am a dog So the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The problem is in fn speak(&self) {
println!("{}", self.greeting());
}
The way out of this is to let the Python runtime resolve the method call target of the internal method: fn speak(slf: Py<Self>, py: Python) -> PyResult<()> {
println!("{}", slf.call_method0(py, "greeting")?);
Ok(())
} |
Beta Was this translation helpful? Give feedback.
The problem is in
speak
:self.greeting()
still follows Rust method resolution, and Rust isn't aware of the class hierarchy defined in pyo3 annotations. This problem would also appear if thegreeting
method was implemented in a Python subclass ofAnimal
.The way out of this is to let the Python runtime resolve the method call target of the internal method: