Methods
The #[pymethods]
attribute is not limited to constructors. You can use it to attach any number of methods to your #[pyclass]
:
#![allow(unused)] fn main() { use pyo3::prelude::*; #[pyclass] struct Wallet { #[pyo3(get, set)] balance: i32, } #[pymethods] impl Wallet { #[new] fn new(balance: i32) -> Self { Wallet { balance } } fn deposit(&mut self, amount: i32) { self.balance += amount; } fn withdraw(&mut self, amount: i32) { self.balance -= amount; } } }
All methods within an impl
block annotated with #[pymethods]
are automatically exposed to Python as methods on
your #[pyclass]
1. The deposit
and withdraw
methods in the example above can be called from Python like this:
wallet = Wallet(0)
wallet.deposit(100)
wallet.withdraw(50)
assert wallet.balance == 50
multiple-pymethods
You can't annotate multiple impl
blocks with #[pymethods]
for the same class, due to a limitation in
Rust's metaprogramming capabilities.
There is a way to work around this issue using some linker dark magic, via the
multiple-pymethods
feature flag, but it comes with a penalty in terms of compile times as well as limited cross-platform support.
Check out pyo3
's documentation for more details.
Footnotes
All methods in a #[pymethods]
block are exposed, even if they are private!
Exercise
The exercise for this section is located in 02_classes/02_methods