summaryrefslogtreecommitdiff
path: root/docs/src/tutorial/cdef_classes.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/src/tutorial/cdef_classes.rst')
-rw-r--r--docs/src/tutorial/cdef_classes.rst97
1 files changed, 73 insertions, 24 deletions
diff --git a/docs/src/tutorial/cdef_classes.rst b/docs/src/tutorial/cdef_classes.rst
index a95b802a8..ec2566dbd 100644
--- a/docs/src/tutorial/cdef_classes.rst
+++ b/docs/src/tutorial/cdef_classes.rst
@@ -1,5 +1,9 @@
+***********************************
Extension types (aka. cdef classes)
-===================================
+***********************************
+
+.. include::
+ ../two-syntax-variants-used
To support object-oriented programming, Cython supports writing normal
Python classes exactly as in Python:
@@ -24,17 +28,33 @@ single inheritance. Normal Python classes, on the other hand, can
inherit from any number of Python classes and extension types, both in
Cython code and pure Python code.
+.. tabs::
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/math_function_2.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/math_function_2.pyx
+
So far our integration example has not been very useful as it only
integrates a single hard-coded function. In order to remedy this,
with hardly sacrificing speed, we will use a cdef class to represent a
function on floating point numbers:
-.. literalinclude:: ../../examples/tutorial/cdef_classes/math_function_2.pyx
-
The directive cpdef makes two versions of the method available; one
fast for use from Cython and one slower for use from Python. Then:
-.. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.pyx
+.. tabs::
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.py
+ :caption: sin_of_square.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.pyx
+ :caption: sin_of_square.pyx
This does slightly more than providing a python wrapper for a cdef
method: unlike a cdef method, a cpdef method is fully overridable by
@@ -43,13 +63,24 @@ little calling overhead compared to a cdef method.
To make the class definitions visible to other modules, and thus allow for
efficient C-level usage and inheritance outside of the module that
-implements them, we define them in a :file:`sin_of_square.pxd` file:
+implements them, we define them in a ``.pxd`` file with the same name
+as the module:
.. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.pxd
+ :caption: sin_of_square.pxd
Using this, we can now change our integration example:
-.. literalinclude:: ../../examples/tutorial/cdef_classes/integrate.pyx
+.. tabs::
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/integrate.py
+ :caption: integrate.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/integrate.pyx
+ :caption: integrate.pyx
This is almost as fast as the previous code, however it is much more flexible
as the function to integrate can be changed. We can even pass in a new
@@ -70,32 +101,50 @@ into a Cython module.
Some notes on our new implementation of ``evaluate``:
- - The fast method dispatch here only works because ``evaluate`` was
- declared in ``Function``. Had ``evaluate`` been introduced in
- ``SinOfSquareFunction``, the code would still work, but Cython
- would have used the slower Python method dispatch mechanism
- instead.
+- The fast method dispatch here only works because ``evaluate`` was
+ declared in ``Function``. Had ``evaluate`` been introduced in
+ ``SinOfSquareFunction``, the code would still work, but Cython
+ would have used the slower Python method dispatch mechanism
+ instead.
- - In the same way, had the argument ``f`` not been typed, but only
- been passed as a Python object, the slower Python dispatch would
- be used.
+- In the same way, had the argument ``f`` not been typed, but only
+ been passed as a Python object, the slower Python dispatch would
+ be used.
- - Since the argument is typed, we need to check whether it is
- ``None``. In Python, this would have resulted in an ``AttributeError``
- when the ``evaluate`` method was looked up, but Cython would instead
- try to access the (incompatible) internal structure of ``None`` as if
- it were a ``Function``, leading to a crash or data corruption.
+- Since the argument is typed, we need to check whether it is
+ ``None``. In Python, this would have resulted in an ``AttributeError``
+ when the ``evaluate`` method was looked up, but Cython would instead
+ try to access the (incompatible) internal structure of ``None`` as if
+ it were a ``Function``, leading to a crash or data corruption.
There is a *compiler directive* ``nonecheck`` which turns on checks
for this, at the cost of decreased speed. Here's how compiler directives
are used to dynamically switch on or off ``nonecheck``:
-.. literalinclude:: ../../examples/tutorial/cdef_classes/nonecheck.pyx
+.. tabs::
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/nonecheck.py
+ :caption: nonecheck.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/nonecheck.pyx
+ :caption: nonecheck.pyx
Attributes in cdef classes behave differently from attributes in regular classes:
- - All attributes must be pre-declared at compile-time
- - Attributes are by default only accessible from Cython (typed access)
- - Properties can be declared to expose dynamic attributes to Python-space
+- All attributes must be pre-declared at compile-time
+- Attributes are by default only accessible from Cython (typed access)
+- Properties can be declared to expose dynamic attributes to Python-space
+
+.. tabs::
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/wave_function.py
+ :caption: wave_function.py
+
+ .. group-tab:: Cython
-.. literalinclude:: ../../examples/tutorial/cdef_classes/wave_function.pyx
+ .. literalinclude:: ../../examples/tutorial/cdef_classes/wave_function.pyx
+ :caption: wave_function.pyx