@@ -61,7 +61,6 @@ impl Number {
6161 // 👇 Tuple field access in Rust uses a dot
6262 format! (" Number({})" , self . 0 )
6363 }
64-
6564 // `__str__` is generally used to create an "informal" representation, so we
6665 // just forward to `i32`'s `ToString` trait implementation to print a bare number.
6766 fn __str__ (& self ) -> String {
@@ -70,6 +69,31 @@ impl Number {
7069}
7170```
7271
72+ #### Accessing the class name
73+
74+ In the ` __repr__ ` , we used a hard-coded class name. This is sometimes not ideal,
75+ because if the class is subclassed in Python, we would like the repr to reflect
76+ the subclass name. This is typically done in Python code by accessing
77+ ` self.__class__.__name__ ` . In order to be able to access the Python type information
78+ * and* the Rust struct, we need to use a ` PyCell ` as the ` self ` argument.
79+
80+ ``` rust
81+ # use pyo3 :: prelude :: * ;
82+ #
83+ # #[pyclass]
84+ # struct Number (i32 );
85+ #
86+ #[pymethods]
87+ impl Number {
88+ fn __repr__ (slf : & PyCell <Self >) -> PyResult <String > {
89+ // This is the equivalent of `self.__class__.__name__` in Python.
90+ let class_name : & str = slf . get_type (). name ()? ;
91+ // To access fields of the Rust struct, we need to borrow the `PyCell`.
92+ Ok (format! (" {}({})" , class_name , slf . borrow (). 0 ))
93+ }
94+ }
95+ ```
96+
7397### Hashing
7498
7599
@@ -235,8 +259,9 @@ impl Number {
235259 Self (value )
236260 }
237261
238- fn __repr__ (& self ) -> String {
239- format! (" Number({})" , self . 0 )
262+ fn __repr__ (slf : & PyCell <Self >) -> PyResult <String > {
263+ let class_name : & str = slf . get_type (). name ()? ;
264+ Ok (format! (" {}({})" , class_name , slf . borrow (). 0 ))
240265 }
241266
242267 fn __str__ (& self ) -> String {
0 commit comments