summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatus Valo <matusvalo@users.noreply.github.com>2021-07-15 09:06:05 +0200
committerGitHub <noreply@github.com>2021-07-15 09:06:05 +0200
commitd7efda4378732b703e6f9125ce5eec1868f71971 (patch)
tree3f3483de8acf937f31bff488b8ae787a1a4df492
parent13125ee70c72453779fde0c020b53e862e3f613e (diff)
downloadcython-d7efda4378732b703e6f9125ce5eec1868f71971.tar.gz
docs: Add pure Python examples to "Getting started" guide (GH-4283)
-rw-r--r--docs/examples/quickstart/cythonize/cdef_keyword.py4
-rw-r--r--docs/examples/quickstart/cythonize/cdef_keyword.pyx2
-rwxr-xr-xdocs/examples/quickstart/cythonize/htmlreport_py.pngbin0 -> 21568 bytes
-rwxr-xr-xdocs/examples/quickstart/cythonize/htmlreport_pyx.pngbin0 -> 19384 bytes
-rw-r--r--docs/examples/quickstart/cythonize/integrate_cy.py13
-rw-r--r--docs/examples/quickstart/cythonize/integrate_cy.pyx3
-rw-r--r--docs/src/quickstart/build.rst32
-rw-r--r--docs/src/quickstart/cythonize.rst59
-rw-r--r--docs/src/quickstart/htmlreport.pngbin19181 -> 0 bytes
9 files changed, 93 insertions, 20 deletions
diff --git a/docs/examples/quickstart/cythonize/cdef_keyword.py b/docs/examples/quickstart/cythonize/cdef_keyword.py
new file mode 100644
index 000000000..6c0ee3e68
--- /dev/null
+++ b/docs/examples/quickstart/cythonize/cdef_keyword.py
@@ -0,0 +1,4 @@
+@cython.cfunc
+@cython.exceptval(-2, check=True)
+def f(x: cython.double) -> cython.double:
+ return x ** 2 - x
diff --git a/docs/examples/quickstart/cythonize/cdef_keyword.pyx b/docs/examples/quickstart/cythonize/cdef_keyword.pyx
index ba1e46272..bc7d893fa 100644
--- a/docs/examples/quickstart/cythonize/cdef_keyword.pyx
+++ b/docs/examples/quickstart/cythonize/cdef_keyword.pyx
@@ -1,2 +1,4 @@
+
+
cdef double f(double x) except? -2:
return x ** 2 - x
diff --git a/docs/examples/quickstart/cythonize/htmlreport_py.png b/docs/examples/quickstart/cythonize/htmlreport_py.png
new file mode 100755
index 000000000..0303f4b6e
--- /dev/null
+++ b/docs/examples/quickstart/cythonize/htmlreport_py.png
Binary files differ
diff --git a/docs/examples/quickstart/cythonize/htmlreport_pyx.png b/docs/examples/quickstart/cythonize/htmlreport_pyx.png
new file mode 100755
index 000000000..bc9cff2f9
--- /dev/null
+++ b/docs/examples/quickstart/cythonize/htmlreport_pyx.png
Binary files differ
diff --git a/docs/examples/quickstart/cythonize/integrate_cy.py b/docs/examples/quickstart/cythonize/integrate_cy.py
new file mode 100644
index 000000000..592ce8db7
--- /dev/null
+++ b/docs/examples/quickstart/cythonize/integrate_cy.py
@@ -0,0 +1,13 @@
+def f(x: cython.double):
+ return x ** 2 - x
+
+
+def integrate_f(a: cython.double, b: cython.double, N: cython.int):
+ i: cython.int
+ s: cython.double
+ dx: cython.double
+ s = 0
+ dx = (b - a) / N
+ for i in range(N):
+ s += f(a + i * dx)
+ return s * dx
diff --git a/docs/examples/quickstart/cythonize/integrate_cy.pyx b/docs/examples/quickstart/cythonize/integrate_cy.pyx
index f676969d8..0e20a6c33 100644
--- a/docs/examples/quickstart/cythonize/integrate_cy.pyx
+++ b/docs/examples/quickstart/cythonize/integrate_cy.pyx
@@ -4,7 +4,8 @@ def f(double x):
def integrate_f(double a, double b, int N):
cdef int i
- cdef double s, dx
+ cdef double s
+ cdef double dx
s = 0
dx = (b - a) / N
for i in range(N):
diff --git a/docs/src/quickstart/build.rst b/docs/src/quickstart/build.rst
index 5382bc663..5d9e8a307 100644
--- a/docs/src/quickstart/build.rst
+++ b/docs/src/quickstart/build.rst
@@ -3,7 +3,7 @@ Building Cython code
Cython code must, unlike Python, be compiled. This happens in two stages:
- - A ``.pyx`` file is compiled by Cython to a ``.c`` file, containing
+ - A ``.pyx`` or ``.py`` file is compiled by Cython to a ``.c`` file, containing
the code of a Python extension module.
- The ``.c`` file is compiled by a C compiler to
a ``.so`` file (or ``.pyd`` on Windows) which can be
@@ -73,14 +73,32 @@ and load the ``Cython`` extension from within the Jupyter notebook::
%load_ext Cython
-Then, prefix a cell with the ``%%cython`` marker to compile it::
+Then, prefix a cell with the ``%%cython`` marker to compile it
- %%cython
+.. tabs::
- cdef int a = 0
- for i in range(10):
- a += i
- print(a)
+ .. group-tab:: Pure Python
+
+ .. code-block:: python
+
+ %%cython
+
+ a: cython.int = 0
+ for i in range(10):
+ a += i
+ print(a)
+
+
+ .. group-tab:: Cython
+
+ .. code-block:: python
+
+ %%cython
+
+ cdef int a = 0
+ for i in range(10):
+ a += i
+ print(a)
You can show Cython's code analysis by passing the ``--annotate`` option::
diff --git a/docs/src/quickstart/cythonize.rst b/docs/src/quickstart/cythonize.rst
index 22cad0470..09cbb470f 100644
--- a/docs/src/quickstart/cythonize.rst
+++ b/docs/src/quickstart/cythonize.rst
@@ -1,6 +1,9 @@
Faster code via static typing
=============================
+.. include::
+ ../two-syntax-variants-used
+
Cython is a Python compiler. This means that it can compile normal
Python code without changes (with a few obvious exceptions of some as-yet
unsupported language features, see :ref:`Cython limitations<cython-limitations>`).
@@ -33,6 +36,7 @@ Typing Variables
Consider the following pure Python code:
.. literalinclude:: ../../examples/quickstart/cythonize/integrate.py
+ :caption: integrate.py
Simply compiling this in Cython merely gives a 35% speedup. This is
better than nothing, but adding some static types can make a much larger
@@ -40,7 +44,17 @@ difference.
With additional type declarations, this might look like:
-.. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.pyx
+.. tabs::
+
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.py
+ :caption: integrate_cy.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.pyx
+ :caption: integrate_cy.pyx
Since the iterator variable ``i`` is typed with C semantics, the for-loop will be compiled
to pure C code. Typing ``a``, ``s`` and ``dx`` is important as they are involved
@@ -55,27 +69,40 @@ Typing Functions
Python function calls can be expensive -- in Cython doubly so because
one might need to convert to and from Python objects to do the call.
-In our example above, the argument is assumed to be a C double both inside f()
+In our example above, the argument is assumed to be a C double both inside ``f()``
and in the call to it, yet a Python ``float`` object must be constructed around the
argument in order to pass it.
-Therefore Cython provides a syntax for declaring a C-style function,
-the cdef keyword:
+Therefore, Cython provides a way for declaring a C-style function,
+the Cython specific ``cdef`` statement, as well as the ``@cfunc`` decorator to
+declare C-style functions in Python syntax. Both approaches are
+equivalent and produce the same C code:
+
+.. tabs::
+
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.py
-.. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.pyx
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.pyx
Some form of except-modifier should usually be added, otherwise Cython
will not be able to propagate exceptions raised in the function (or a
function it calls). The ``except? -2`` means that an error will be checked
for if ``-2`` is returned (though the ``?`` indicates that ``-2`` may also
-be used as a valid return value).
+be used as a valid return value). The same can be expressed using only Python
+syntax with the decorator ``@exceptval(-2, check=True)``.
+
Alternatively, the slower ``except *`` is always
safe. An except clause can be left out if the function returns a Python
object or if it is guaranteed that an exception will not be raised
-within the function call.
+within the function call. Again, Cython provides the decorator ``@exceptval(check=True)``
+providing the same functionality.
-A side-effect of cdef is that the function is no longer available from
-Python-space, as Python wouldn't know how to call it. It is also no
+A side-effect of ``cdef`` (and the ``@cfunc`` decorator) is that the function is no longer
+visible from Python-space, as Python wouldn't know how to call it. It is also no
longer possible to change :func:`f` at runtime.
Using the ``cpdef`` keyword instead of ``cdef``, a Python wrapper is also
@@ -84,7 +111,8 @@ typed values directly) and from Python (wrapping values in Python
objects). In fact, ``cpdef`` does not just provide a Python wrapper, it also
installs logic to allow the method to be overridden by python methods, even
when called from within cython. This does add a tiny overhead compared to ``cdef``
-methods.
+methods. Again, Cython provides a ``@ccall`` decorator which provides the same
+functionality as ``cpdef`` keyword.
Speedup: 150 times over pure Python.
@@ -118,7 +146,15 @@ This report is invaluable when optimizing a function for speed,
and for determining when to :ref:`release the GIL <nogil>`:
in general, a ``nogil`` block may contain only "white" code.
-.. figure:: htmlreport.png
+.. tabs::
+
+ .. group-tab:: Pure Python
+
+ .. figure:: htmlreport_py.png
+
+ .. group-tab:: Cython
+
+ .. figure:: htmlreport_pyx.png
Note that Cython deduces the type of local variables based on their assignments
(including as loop variable targets) which can also cut down on the need to
@@ -135,4 +171,3 @@ with this language feature. It can be of great help to cut down on the need to t
everything, but it also can lead to surprises. Especially if one isn't familiar with
arithmetic expressions with c types. A quick overview of those
can be found `here <https://www.eskimo.com/~scs/cclass/int/sx4cb.html>`_.
-
diff --git a/docs/src/quickstart/htmlreport.png b/docs/src/quickstart/htmlreport.png
deleted file mode 100644
index 0fc5e7bbe..000000000
--- a/docs/src/quickstart/htmlreport.png
+++ /dev/null
Binary files differ