You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guide/src/class.md
+36-34Lines changed: 36 additions & 34 deletions
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,8 @@
2
2
3
3
## Define new class
4
4
5
-
To define python custom class, rust struct needs to be annotated with `#[pyclass]` attribute.
5
+
To define a custom python class, a rust struct needs to be annotated with the
6
+
`#[pyclass]` attribute.
6
7
7
8
```rust
8
9
# usepyo3::prelude::*;
@@ -19,12 +20,12 @@ The above example generates implementations for `PyTypeInfo` and `PyTypeObject`
19
20
## Get Python objects from `pyclass`
20
21
You can use `pyclass`es like normal rust structs.
21
22
22
-
However, if instantiate noramlly, you can't treat `pyclass`es as Python objects.
23
+
However, if instantiated normally, you can't treat `pyclass`es as Python objects.
23
24
24
25
To get a Python object which includes `pyclass`, we have to use some special methods.
25
26
26
27
### `PyRef`
27
-
`PyRef` is a special reference, which ensures that the reffrered struct is a part of
28
+
`PyRef` is a special reference, which ensures that the referred struct is a part of
28
29
a Python object, and you are also holding the GIL.
29
30
30
31
You can get an instance of `PyRef` by `PyRef::new`, which does 3 things:
@@ -219,7 +220,7 @@ Getter or setter function's name is used as property name by default. There are
219
220
ways how to override name.
220
221
221
222
If function name starts with `get_` or `set_` for getter or setter respectively.
222
-
Descriptor name becomes function name with prefix removed. This is useful in case os
223
+
Descriptor name becomes function name with prefix removed. This is useful in case of
223
224
rust's special keywords like `type`.
224
225
225
226
```rust
@@ -248,7 +249,7 @@ impl MyClass {
248
249
In this case property `num` is defined. And it is available from python code as `self.num`.
249
250
250
251
Also both `#[getter]` and `#[setter]` attributes accepts one parameter.
251
-
If parameter is specified, it is used and property name. i.e.
252
+
If this parameter is specified, it is used as a property name. i.e.
252
253
253
254
```rust
254
255
# usepyo3::prelude::*;
@@ -273,7 +274,7 @@ impl MyClass {
273
274
}
274
275
```
275
276
276
-
In this case property `number` is defined. And it is available from python code as `self.number`.
277
+
In this case the property `number` is defined and is available from python code as `self.number`.
277
278
278
279
For simple cases you can also define getters and setters in your Rust struct field definition, for example:
279
280
@@ -290,10 +291,9 @@ Then it is available from Python code as `self.num`.
290
291
291
292
## Instance methods
292
293
293
-
To define python compatible method, `impl` block for struct has to be annotated
294
-
with `#[pymethods]` attribute. `pyo3` library generates python compatible
295
-
wrappers for all functions in this block with some variations, like descriptors,
296
-
class method static methods, etc.
294
+
To define a python compatible method, `impl` block for struct has to be annotated with the
295
+
`#[pymethods]` attribute. PyO3 generates python compatible wrappers for all functions in this
296
+
block with some variations, like descriptors, class method static methods, etc.
297
297
298
298
```rust
299
299
# usepyo3::prelude::*;
@@ -342,8 +342,8 @@ From python perspective `method2`, in above example, does not accept any argumen
342
342
343
343
## Class methods
344
344
345
-
To specify class method for custom class, method needs to be annotated
346
-
with`#[classmethod]` attribute.
345
+
To specify a class method for a custom class, the method needs to be annotated
346
+
with the `#[classmethod]` attribute.
347
347
348
348
```rust
349
349
# usepyo3::prelude::*;
@@ -373,9 +373,9 @@ Declares a class method callable from Python.
373
373
374
374
## Static methods
375
375
376
-
To specify class method for custom class, method needs to be annotated
377
-
with `#[staticmethod]` attribute. The return type must be `PyResult<T>`
378
-
for some `T` that implements `IntoPyObject`.
376
+
To specify a static method for a custom class, method needs to be annotated with
377
+
`#[staticmethod]` attribute. The return type must be `PyResult<T>` for some `T` that implements
378
+
`IntoPyObject`.
379
379
380
380
```rust
381
381
# usepyo3::prelude::*;
@@ -396,8 +396,8 @@ impl MyClass {
396
396
397
397
## Callable object
398
398
399
-
To specify custom `__call__` method for custom class, call method needs to be annotated
400
-
with`#[call]` attribute. Arguments of the method are specified same as for instance method.
399
+
To specify a custom `__call__` method for a custom class, call methods need to be annotated with
400
+
the`#[call]` attribute. Arguments of the method are specified same as for instance method.
401
401
402
402
```rust
403
403
# usepyo3::prelude::*;
@@ -421,14 +421,13 @@ impl MyClass {
421
421
422
422
## Method arguments
423
423
424
-
By default pyo3 library uses function signature to determine which arguments are required.
425
-
Then it scans incoming `args` parameter and then incoming `kwargs` parameter. If it can not
426
-
find all required parameters, it raises `TypeError` exception.
427
-
It is possible to override default behavior with `#[args(...)]` attribute. `args` attribute
428
-
accept comma separated list of parameters in form `attr_name="default value"`. Each parameter
429
-
has to match method parameter by name.
424
+
By default PyO3 uses function signatures to determine which arguments are required. Then it scans
425
+
incoming `args` parameter and then incoming `kwargs` parameter. If it can not find all required
426
+
parameters, it raises a `TypeError` exception. It is possible to override the default behavior
427
+
with `#[args(...)]` attribute. `args` attribute accepts a comma separated list of parameters in
428
+
form of `attr_name="default value"`. Each parameter has to match the method parameter by name.
430
429
431
-
Each parameter could one of following type:
430
+
Each parameter could be one of following type:
432
431
433
432
* "\*": var arguments separator, each parameter defined after "*" is keyword only parameters.
434
433
corresponds to python's `def meth(*, arg1.., arg2=..)`
@@ -438,7 +437,7 @@ Each parameter could one of following type:
438
437
Type of `kwargs` parameter has to be `Option<&PyDict>`.
439
438
* arg="Value": arguments with default value. corresponds to python's `def meth(arg=Value)`.
440
439
if `arg` argument is defined after var arguments it is treated as keyword argument.
441
-
Note that `Value` has to be valid rust code, pyo3 just inserts it into generated
440
+
Note that `Value` has to be valid rust code, PyO3 just inserts it into generated
442
441
code unmodified.
443
442
444
443
Example:
@@ -464,11 +463,10 @@ impl MyClass {
464
463
465
464
## Class customizations
466
465
467
-
Python object model defines several protocols for different object behavior,
468
-
like sequence, mapping or number protocols. pyo3 library defines separate trait for each
469
-
of them. To provide specific python object behavior you need to implement specific trait
470
-
for your struct. Important note, each protocol implementation block has to be annotated
471
-
with `#[pyproto]` attribute.
466
+
Python's object model defines several protocols for different object behavior, like sequence,
467
+
mapping or number protocols. PyO3 defines separate traits for each of them. To provide specific
468
+
python object behavior you need to implement the specific trait for your struct. Important note,
469
+
each protocol implementation block has to be annotated with `#[pyproto]` attribute.
472
470
473
471
### Basic object customization
474
472
@@ -527,7 +525,7 @@ Each methods corresponds to python's `self.attr`, `self.attr = value` and `del s
527
525
528
526
*`fn __bool__(&self) -> PyResult<bool>`
529
527
530
-
Determines the "truthyness" of the object.
528
+
Determines the "truthiness" of the object.
531
529
This method works for both python 3 and python 2,
532
530
even on Python 2.7 where the Python spelling was `__nonzero__`.
533
531
@@ -574,9 +572,9 @@ impl PyGCProtocol for ClassWithGCSupport {
574
572
}
575
573
```
576
574
577
-
Special protocol trait implementation has to be annotated with `#[pyproto]` attribute.
575
+
Special protocol trait implementations have to be annotated with the`#[pyproto]` attribute.
578
576
579
-
It is also possible to enable gc for custom class using `gc` parameter for `class` annotation.
577
+
It is also possible to enable GC for custom class using `gc` parameter for `class` annotation.
580
578
i.e. `#[pyclass(gc)]`. In that case instances of custom class participate in python garbage
581
579
collector, and it is possible to track them with `gc` module methods.
582
580
@@ -618,6 +616,10 @@ TODO: Which traits to implement (basically `PyTypeCreate: PyObjectAlloc + PyType
618
616
619
617
## How methods are implemented
620
618
621
-
Users should be able to define a `#[pyclass]` with or without `#[pymethods]`, while pyo3 needs a trait with a function that returns all methods. Since it's impossible make the code generation in pyclass dependent on whether there is an impl block, we'd need to make to implement the trait on `#[pyclass]` and override the implementation in `#[pymethods]`, which is to my best knowledge only possible with the specialization feature, which is can't be used on stable.
619
+
Users should be able to define a `#[pyclass]` with or without `#[pymethods]`, while PyO3 needs a
620
+
trait with a function that returns all methods. Since it's impossible to make the code generation in
621
+
pyclass dependent on whether there is an impl block, we'd need to implement the trait on
622
+
`#[pyclass]` and override the implementation in `#[pymethods]`, which is to the best of my knowledge
623
+
only possible with the specialization feature, which can't be used on stable.
622
624
623
625
To escape this we use [inventory](https://github.com/dtolnay/inventory), which allows us to collect `impl`s from arbitrary source code by exploiting some binary trick. See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) and `pyo3_derive_backend::py_class::impl_inventory` for more details.
0 commit comments