docs: show pattern for self.__class__.__name__ in __repr__

Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com>
This commit is contained in:
Will Jones 2023-03-26 15:28:46 -07:00 committed by Adam Reichold
parent ebedcfb8b2
commit 52a0378e56
2 changed files with 32 additions and 5 deletions

View File

@ -233,8 +233,10 @@ impl Number {
Self(value)
}
fn __repr__(&self) -> String {
format!("Number({})", self.0)
fn __repr__(slf: &PyCell<Self>) -> PyResult<String> {
// Get the class name dynamically in case `Number` is subclassed
let class_name: &str = slf.get_type().name()?;
Ok(format!("{}({})", class_name, slf.borrow().0))
}
fn __str__(&self) -> String {

View File

@ -61,7 +61,6 @@ impl Number {
// 👇 Tuple field access in Rust uses a dot
format!("Number({})", self.0)
}
// `__str__` is generally used to create an "informal" representation, so we
// just forward to `i32`'s `ToString` trait implementation to print a bare number.
fn __str__(&self) -> String {
@ -70,6 +69,31 @@ impl Number {
}
```
#### Accessing the class name
In the `__repr__`, we used a hard-coded class name. This is sometimes not ideal,
because if the class is subclassed in Python, we would like the repr to reflect
the subclass name. This is typically done in Python code by accessing
`self.__class__.__name__`. In order to be able to access the Python type information
*and* the Rust struct, we need to use a `PyCell` as the `self` argument.
```rust
# use pyo3::prelude::*;
#
# #[pyclass]
# struct Number(i32);
#
#[pymethods]
impl Number {
fn __repr__(slf: &PyCell<Self>) -> PyResult<String> {
// This is the equivalent of `self.__class__.__name__` in Python.
let class_name: &str = slf.get_type().name()?;
// To access fields of the Rust struct, we need to borrow the `PyCell`.
Ok(format!("{}({})", class_name, slf.borrow().0))
}
}
```
### Hashing
@ -235,8 +259,9 @@ impl Number {
Self(value)
}
fn __repr__(&self) -> String {
format!("Number({})", self.0)
fn __repr__(slf: &PyCell<Self>) -> PyResult<String> {
let class_name: &str = slf.get_type().name()?;
Ok(format!("{}({})", class_name, slf.borrow().0))
}
fn __str__(&self) -> String {