Merge pull request #1832 from mejrs/decorator

guide: add decorator example
This commit is contained in:
David Hewitt 2021-08-26 18:55:59 +01:00 committed by GitHub
commit a2375f336f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 55 additions and 11 deletions

View File

@ -614,25 +614,69 @@ impl MyClass {
To specify a custom `__call__` method for a custom class, the method needs to be annotated with To specify a custom `__call__` method for a custom class, the method needs to be annotated with
the `#[call]` attribute. Arguments of the method are specified as for instance methods. the `#[call]` attribute. Arguments of the method are specified as for instance methods.
The following pyclass is a basic decorator - its constructor takes a Python object
as argument and calls that object when called.
```rust ```rust
# use pyo3::prelude::*; # use pyo3::prelude::*;
use pyo3::types::PyTuple; # use pyo3::types::{PyDict, PyTuple};
# #[pyclass] #
# struct MyClass { #[pyclass(name = "counter")]
# num: i32, struct PyCounter {
# debug: bool, count: u64,
# } wraps: Py<PyAny>,
}
#[pymethods] #[pymethods]
impl MyClass { impl PyCounter {
#[new]
fn __new__(wraps: Py<PyAny>) -> Self {
PyCounter { count: 0, wraps }
}
#[call] #[call]
#[args(args="*")] #[args(args = "*", kwargs = "**")]
fn __call__(&self, args: &PyTuple) -> PyResult<i32> { fn __call__(
println!("MyClass has been called"); &mut self,
Ok(self.num) py: Python,
args: &PyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<Py<PyAny>> {
self.count += 1;
let name = self.wraps.getattr(py, "__name__").unwrap();
println!("{} has been called {} time(s).", name, self.count);
self.wraps.call(py, args, kwargs)
} }
} }
``` ```
Python code:
```python
@counter
def say_hello():
print("hello")
say_hello()
say_hello()
say_hello()
say_hello()
```
Output:
```text
say_hello has been called 1 time(s).
hello
say_hello has been called 2 time(s).
hello
say_hello has been called 3 time(s).
hello
say_hello has been called 4 time(s).
hello
```
## Method arguments ## Method arguments
By default, PyO3 uses function signatures to determine which arguments are required. Then it scans By default, PyO3 uses function signatures to determine which arguments are required. Then it scans