Merge pull request #1832 from mejrs/decorator
guide: add decorator example
This commit is contained in:
commit
a2375f336f
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue