Commit 555cf2e1 authored by 0dminnimda's avatar 0dminnimda Committed by GitHub

Pythonise the documentation according to #4187: Basic Tutorial (cython_tutorial.rst) (GH-4226)

See https://github.com/cython/cython/issues/4187

* .gitignore: add directory for docs build and cython_debug
* doc-requirements.txt: add sphinx-tabs
* conf.py: add and setup sphinx-tabs extension
* Create _static\css\tabs.css for customisation
* add "two-syntax-variants-used" file as a preface about the different typing variants
parent b19b8d84
...@@ -24,6 +24,7 @@ Demos/*/*.html ...@@ -24,6 +24,7 @@ Demos/*/*.html
/TEST_TMP/ /TEST_TMP/
/build/ /build/
/cython_build/ /cython_build/
cython_debug/
/wheelhouse*/ /wheelhouse*/
!tests/build/ !tests/build/
/dist/ /dist/
...@@ -42,6 +43,7 @@ callgrind.out.* ...@@ -42,6 +43,7 @@ callgrind.out.*
.ipynb_checkpoints .ipynb_checkpoints
docs/build docs/build
docs/_build
tags tags
TAGS TAGS
......
.sphinx-tabs {
margin-bottom: 1rem;
}
[role="tablist"] {
border-bottom: 0px solid #a0b3bf;
}
.sphinx-tabs-tab {
position: relative;
font-family: 'Helvetica Neue',Arial,Helvetica,sans-serif;
color: black;
line-height: 24px;
margin: 0;
font-size: 16px;
font-weight: 400;
background-color: rgba(255, 255, 255, 0);
border-radius: 5px 5px 5px 5px;
border: 0;
padding: 0.5rem 1.6rem;
margin-bottom: 0;
}
.sphinx-tabs-tab[aria-selected="true"] {
border: 2px solid gray;
border-bottom: 2px solid gray;
margin: -2px;
background-color: #efefef;
z-index: 999; /* render on top*/
}
.sphinx-tabs-tab[aria-selected="false"] {
border: 2px solid #dddddd;
border-bottom: 2px solid #dddddd;
margin: -2px;
background-color: white;
}
.sphinx-tabs-tab:focus {
z-index: 1;
outline-offset: 1px;
}
.sphinx-tabs-panel {
position: relative;
padding: 0rem;
border: 0px solid #a0b3bf;
margin: 0px 0px 0px 0px;
border-radius: 0 0 5px 5px;
border-top: 0;
background: white;
}
.sphinx-tabs-panel.code-tab {
padding: 0.4rem;
}
.sphinx-tab img {
margin-bottom: 24 px;
}
...@@ -39,6 +39,7 @@ extensions = [ ...@@ -39,6 +39,7 @@ extensions = [
'sphinx.ext.intersphinx', 'sphinx.ext.intersphinx',
'sphinx.ext.autodoc', 'sphinx.ext.autodoc',
'sphinx_issues', # if this is missing, pip install sphinx-issues 'sphinx_issues', # if this is missing, pip install sphinx-issues
'sphinx_tabs.tabs', # if this is missing, pip install sphinx-tabs
] ]
try: import rst2pdf try: import rst2pdf
...@@ -133,6 +134,10 @@ imgmath_image_format = "svg" ...@@ -133,6 +134,10 @@ imgmath_image_format = "svg"
issues_github_path = "cython/cython" issues_github_path = "cython/cython"
# For sphinx-tabs
sphinx_tabs_disable_tab_closing = True
# -- Options for HTML output --------------------------------------------------- # -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
...@@ -174,6 +179,11 @@ html_favicon = "_static/favicon.ico" ...@@ -174,6 +179,11 @@ html_favicon = "_static/favicon.ico"
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ['_static']
# Overwriting css from extensions
html_context = {
'css_files': ['_static/css/tabs.css'],
}
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format. # using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y' #html_last_updated_fmt = '%b %d, %Y'
......
def primes(nb_primes: cython.int):
i: cython.int
p: cython.int[1000]
if nb_primes > 1000:
nb_primes = 1000
if not cython.compiled: # Only if regular Python is running
p = [0] * 1000 # Make p work almost like a C array
len_p: cython.int = 0 # The current number of elements in p.
n: cython.int = 2
while len_p < nb_primes:
# Is n prime?
for i in p[:len_p]:
if n % i == 0:
break
# If no break occurred in the loop, we have a prime.
else:
p[len_p] = n
len_p += 1
n += 1
# Let's copy the result into a Python list:
result_as_list = [prime for prime in p[:len_p]]
return result_as_list
def primes(int nb_primes): def primes(int nb_primes):
cdef int n, i, len_p cdef int n, i, len_p
cdef int p[1000] cdef int p[1000]
if nb_primes > 1000: if nb_primes > 1000:
nb_primes = 1000 nb_primes = 1000
len_p = 0 # The current number of elements in p. len_p = 0 # The current number of elements in p.
n = 2 n = 2
while len_p < nb_primes: while len_p < nb_primes:
...@@ -18,6 +22,6 @@ def primes(int nb_primes): ...@@ -18,6 +22,6 @@ def primes(int nb_primes):
len_p += 1 len_p += 1
n += 1 n += 1
# Let's return the result in a python list: # Let's copy the result into a Python list:
result_as_list = [prime for prime in p[:len_p]] result_as_list = [prime for prime in p[:len_p]]
return result_as_list return result_as_list
# distutils: language=c++
import cython
from cython.cimports.libcpp.vector import vector
def primes(nb_primes: cython.uint):
i: cython.int
p: vector[cython.int]
p.reserve(nb_primes) # allocate memory for 'nb_primes' elements.
n: cint = 2
while p.size() < nb_primes: # size() for vectors is similar to len()
for i in p:
if n % i == 0:
break
else:
p.push_back(n) # push_back is similar to append()
n += 1
# If possible, C values and C++ objects are automatically
# converted to Python objects at need.
return p # so here, the vector will be copied into a Python list.
# distutils: language=c++ # distutils: language=c++
from libcpp.vector cimport vector from libcpp.vector cimport vector
def primes(unsigned int nb_primes): def primes(unsigned int nb_primes):
...@@ -16,6 +17,6 @@ def primes(unsigned int nb_primes): ...@@ -16,6 +17,6 @@ def primes(unsigned int nb_primes):
p.push_back(n) # push_back is similar to append() p.push_back(n) # push_back is similar to append()
n += 1 n += 1
# Vectors are automatically converted to Python # If possible, C values and C++ objects are automatically
# lists when converted to Python objects. # converted to Python objects at need.
return p return p # so here, the vector will be copied into a Python list.
def primes_python(nb_primes): def primes(nb_primes):
p = [] p = []
n = 2 n = 2
while len(p) < nb_primes: while len(p) < nb_primes:
......
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("fib.pyx"),
)
.. warning::
This code uses an external native (non-Python) library through a ``cimport``.
Cython compilation enables this, but there is no support for this from
plain Python. Trying to run this code from Python (without compilation)
will fail when accessing the external library.
This is described in more detail in :ref:`calling-c-functions`.
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
Basic Tutorial Basic Tutorial
************** **************
.. include::
../two-syntax-variants-used
The Basics of Cython The Basics of Cython
==================== ====================
...@@ -103,9 +106,14 @@ Now following the steps for the Hello World example we first rename the file ...@@ -103,9 +106,14 @@ Now following the steps for the Hello World example we first rename the file
to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the
:file:`setup.py` file. Using the file created for the Hello World example, all :file:`setup.py` file. Using the file created for the Hello World example, all
that you need to change is the name of the Cython filename, and the resulting that you need to change is the name of the Cython filename, and the resulting
module name, doing this we have: module name, doing this we have::
from setuptools import setup
from Cython.Build import cythonize
.. literalinclude:: ../../examples/tutorial/cython_tutorial/setup.py setup(
ext_modules=cythonize("fib.pyx"),
)
Build the extension with the same command used for the helloworld.pyx: Build the extension with the same command used for the helloworld.pyx:
...@@ -127,29 +135,59 @@ Primes ...@@ -127,29 +135,59 @@ Primes
Here's a small example showing some of what can be done. It's a routine for Here's a small example showing some of what can be done. It's a routine for
finding prime numbers. You tell it how many primes you want, and it returns finding prime numbers. You tell it how many primes you want, and it returns
them as a Python list. them as a Python list.
.. tabs::
.. group-tab:: Pure Python
:file:`primes.pyx`: .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py
:linenos:
:caption: primes.py
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx .. group-tab:: Cython
:linenos:
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:linenos:
:caption: primes.pyx
You'll see that it starts out just like a normal Python function definition, You'll see that it starts out just like a normal Python function definition,
except that the parameter ``nb_primes`` is declared to be of type ``int`` . This except that the parameter ``nb_primes`` is declared to be of type ``int``. This
means that the object passed will be converted to a C integer (or a means that the object passed will be converted to a C integer (or a
``TypeError.`` will be raised if it can't be). ``TypeError.`` will be raised if it can't be).
Now, let's dig into the core of the function:: Now, let's dig into the core of the function:
.. tabs::
.. group-tab:: Pure Python
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py
:lines: 2,3
:dedent:
:lineno-start: 2
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py
:lines: 11,12
:dedent:
:lineno-start: 11
Lines 2, 3, 11 and 12 use the variable annotations
to define some local C variables.
The result is stored in the C array ``p`` during processing,
and will be copied into a Python list at the end (line 26).
.. group-tab:: Cython
cdef int n, i, len_p .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
cdef int p[1000] :lines: 2,3
:dedent:
:lineno-start: 2
Lines 2 and 3 use the ``cdef`` statement to define some local C variables. Lines 2 and 3 use the ``cdef`` statement to define some local C variables.
The result is stored in the C array ``p`` during processing, The result is stored in the C array ``p`` during processing,
and will be copied into a Python list at the end (line 22). and will be copied into a Python list at the end (line 26).
.. NOTE:: You cannot create very large arrays in this manner, because .. NOTE:: You cannot create very large arrays in this manner, because
they are allocated on the C function call :term:`stack<Stack allocation>`, which is a they are allocated on the C function call :term:`stack<Stack allocation>`,
rather precious and scarce resource. which is a rather precious and scarce resource.
To request larger arrays, To request larger arrays,
or even arrays with a length only known at runtime, or even arrays with a length only known at runtime,
you can learn how to make efficient use of you can learn how to make efficient use of
...@@ -157,61 +195,83 @@ and will be copied into a Python list at the end (line 22). ...@@ -157,61 +195,83 @@ and will be copied into a Python list at the end (line 22).
:ref:`Python arrays <array-array>` :ref:`Python arrays <array-array>`
or :ref:`NumPy arrays <memoryviews>` with Cython. or :ref:`NumPy arrays <memoryviews>` with Cython.
:: .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:lines: 5,6
if nb_primes > 1000: :dedent:
nb_primes = 1000 :lineno-start: 5
As in C, declaring a static array requires knowing the size at compile time. As in C, declaring a static array requires knowing the size at compile time.
We make sure the user doesn't set a value above 1000 (or we would have a We make sure the user doesn't set a value above 1000 (or we would have a
segmentation fault, just like in C). :: segmentation fault, just like in C)
.. tabs::
.. group-tab:: Pure Python
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py
:lines: 8,9
:dedent:
:lineno-start: 8
When we run this code from Python, we have to initialize the items in the array.
This is most easily done by filling it with zeros (as seen on line 8-9).
When we compile this with Cython, on the other hand, the array will
behave as in C. It is allocated on the function call stack with a fixed
length of 1000 items that contain arbitrary data from the last time that
memory was used. We will then overwrite those items in our calculation.
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py
:lines: 10-13
:dedent:
:lineno-start: 10
len_p = 0 # The number of elements in p .. group-tab:: Cython
n = 2
while len_p < nb_primes:
Lines 7-9 set up for a loop which will test candidate numbers for primeness .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
until the required number of primes has been found. :: :lines: 10-13
:dedent:
:lineno-start: 10
# Is n prime? Lines 11-13 set up a while loop which will test numbers-candidates to primes
for i in p[:len_p]: until the required number of primes has been found.
if n % i == 0:
break
Lines 11-12, which try dividing a candidate by all the primes found so far, .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:lines: 14-17
:dedent:
:lineno-start: 14
Lines 15-16, which try to divide a candidate by all the primes found so far,
are of particular interest. Because no Python objects are referred to, are of particular interest. Because no Python objects are referred to,
the loop is translated entirely into C code, and thus runs very fast. the loop is translated entirely into C code, and thus runs very fast.
You will notice the way we iterate over the ``p`` C array. :: You will notice the way we iterate over the ``p`` C array.
for i in p[:len_p]: .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:lines: 15
:dedent:
:lineno-start: 15
The loop gets translated into a fast C loop and works just like iterating The loop gets translated into a fast C loop and works just like iterating
over a Python list or NumPy array. If you don't slice the C array with over a Python list or NumPy array. If you don't slice the C array with
``[:len_p]``, then Cython will loop over the 1000 elements of the array. ``[:len_p]``, then Cython will loop over the 1000 elements of the array.
:: .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:lines: 19-23
# If no break occurred in the loop :dedent:
else: :lineno-start: 19
p[len_p] = n
len_p += 1
n += 1
If no breaks occurred, it means that we found a prime, and the block of code If no breaks occurred, it means that we found a prime, and the block of code
after the ``else`` line 16 will be executed. We add the prime found to ``p``. after the ``else`` line 20 will be executed. We add the prime found to ``p``.
If you find having an ``else`` after a for-loop strange, just know that it's a If you find having an ``else`` after a for-loop strange, just know that it's a
lesser known features of the Python language, and that Cython executes it at lesser known features of the Python language, and that Cython executes it at
C speed for you. C speed for you.
If the for-else syntax confuses you, see this excellent If the for-else syntax confuses you, see this excellent
`blog post <https://shahriar.svbtle.com/pythons-else-clause-in-loops>`_. `blog post <https://shahriar.svbtle.com/pythons-else-clause-in-loops>`_.
:: .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:lines: 25-27
# Let's put the result in a python list: :dedent:
result_as_list = [prime for prime in p[:len_p]] :lineno-start: 25
return result_as_list
In line 22, before returning the result, we need to copy our C array into a In line 26, before returning the result, we need to copy our C array into a
Python list, because Python can't read C arrays. Cython can automatically Python list, because Python can't read C arrays. Cython can automatically
convert many C types from and to Python types, as described in the convert many C types from and to Python types, as described in the
documentation on :ref:`type conversion <type-conversion>`, so we can use documentation on :ref:`type conversion <type-conversion>`, so we can use
...@@ -225,11 +285,20 @@ Because the variable ``result_as_list`` hasn't been explicitly declared with a t ...@@ -225,11 +285,20 @@ Because the variable ``result_as_list`` hasn't been explicitly declared with a t
it is assumed to hold a Python object, and from the assignment, Cython also knows it is assumed to hold a Python object, and from the assignment, Cython also knows
that the exact type is a Python list. that the exact type is a Python list.
Finally, at line 18, a normal Finally, at line 27, a normal Python return statement returns the result list.
Python return statement returns the result list.
.. tabs::
.. group-tab:: Pure Python
Compiling primes.py with the Cython compiler produces an extension module
which we can try out in the interactive interpreter as follows:
Compiling primes.pyx with the Cython compiler produces an extension module .. group-tab:: Cython
which we can try out in the interactive interpreter as follows::
Compiling primes.pyx with the Cython compiler produces an extension module
which we can try out in the interactive interpreter as follows:
.. code-block:: python
>>> import primes >>> import primes
>>> primes.primes(10) >>> primes.primes(10)
...@@ -238,12 +307,20 @@ which we can try out in the interactive interpreter as follows:: ...@@ -238,12 +307,20 @@ which we can try out in the interactive interpreter as follows::
See, it works! And if you're curious about how much work Cython has saved you, See, it works! And if you're curious about how much work Cython has saved you,
take a look at the C code generated for this module. take a look at the C code generated for this module.
Cython has a way to visualise where interaction with Python objects and Cython has a way to visualise where interaction with Python objects and
Python's C-API is taking place. For this, pass the Python's C-API is taking place. For this, pass the
``annotate=True`` parameter to ``cythonize()``. It produces a HTML file. Let's see: ``annotate=True`` parameter to ``cythonize()``. It produces a HTML file. Let's see:
.. figure:: htmlreport.png .. tabs::
.. group-tab:: Pure Python
.. figure:: htmlreport_py.png
:scale: 90 %
.. group-tab:: Cython
.. figure:: htmlreport_pyx.png
:scale: 90 %
If a line is white, it means that the code generated doesn't interact If a line is white, it means that the code generated doesn't interact
with Python, so will run as fast as normal C code. The darker the yellow, the more with Python, so will run as fast as normal C code. The darker the yellow, the more
...@@ -262,42 +339,64 @@ Python behavior, the language will perform division checks at runtime, ...@@ -262,42 +339,64 @@ Python behavior, the language will perform division checks at runtime,
just like Python does. You can deactivate those checks by using the just like Python does. You can deactivate those checks by using the
:ref:`compiler directives<compiler-directives>`. :ref:`compiler directives<compiler-directives>`.
Now let's see if, even if we have division checks, we obtained a boost in speed. Now let's see if we get a speed increase even if there is a division check.
Let's write the same program, but Python-style: Let's write the same program, but in Python:
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_python.py .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_python.py
:caption: primes_python.py / primes_python_compiled.py
It is also possible to take a plain ``.py`` file and to compile it with Cython. It is possible to take a plain (unannotated) ``.py`` file and to compile it with Cython.
Let's take ``primes_python``, change the function name to ``primes_python_compiled`` and Let's create a copy of ``primes_python`` and name it ``primes_python_compiled``
compile it with Cython (without changing the code). We will also change the name of the to be able to compare it to the (non-compiled) Python module.
file to ``example_py_cy.py`` to differentiate it from the others. Then we compile that file with Cython, without changing the code.
Now the ``setup.py`` looks like this:: Now the ``setup.py`` looks like this:
from setuptools import setup .. tabs::
from Cython.Build import cythonize .. group-tab:: Pure Python
setup( .. code-block:: python
ext_modules=cythonize(['example.pyx', # Cython code file with primes() function
'example_py_cy.py'], # Python code file with primes_python_compiled() function from setuptools import setup
annotate=True), # enables generation of the html annotation file from Cython.Build import cythonize
)
setup(
ext_modules=cythonize(
['primes.py', # Cython code file with primes() function
'primes_python_compiled.py'], # Python code file with primes() function
annotate=True), # enables generation of the html annotation file
)
.. group-tab:: Cython
.. code-block:: python
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize(
['primes.pyx', # Cython code file with primes() function
'primes_python_compiled.py'], # Python code file with primes() function
annotate=True), # enables generation of the html annotation file
)
Now we can ensure that those two programs output the same values:: Now we can ensure that those two programs output the same values::
>>> primes_python(1000) == primes(1000) >>> import primes, primes_python, primes_python_compiled
>>> primes_python.primes(1000) == primes.primes(1000)
True True
>>> primes_python_compiled(1000) == primes(1000) >>> primes_python_compiled.primes(1000) == primes.primes(1000)
True True
It's possible to compare the speed now:: It's possible to compare the speed now::
python -m timeit -s 'from example_py import primes_python' 'primes_python(1000)' python -m timeit -s 'from primes_python import primes' 'primes(1000)'
10 loops, best of 3: 23 msec per loop 10 loops, best of 3: 23 msec per loop
python -m timeit -s 'from example_py_cy import primes_python_compiled' 'primes_python_compiled(1000)' python -m timeit -s 'from primes_python_compiled import primes' 'primes(1000)'
100 loops, best of 3: 11.9 msec per loop 100 loops, best of 3: 11.9 msec per loop
python -m timeit -s 'from example import primes' 'primes(1000)' python -m timeit -s 'from primes import primes' 'primes(1000)'
1000 loops, best of 3: 1.65 msec per loop 1000 loops, best of 3: 1.65 msec per loop
The cythonize version of ``primes_python`` is 2 times faster than the Python one, The cythonize version of ``primes_python`` is 2 times faster than the Python one,
...@@ -325,9 +424,9 @@ Primes with C++ ...@@ -325,9 +424,9 @@ Primes with C++
With Cython, it is also possible to take advantage of the C++ language, notably, With Cython, it is also possible to take advantage of the C++ language, notably,
part of the C++ standard library is directly importable from Cython code. part of the C++ standard library is directly importable from Cython code.
Let's see what our :file:`primes.pyx` becomes when Let's see what our code becomes when using
using `vector <https://en.cppreference.com/w/cpp/container/vector>`_ from the C++ `vector <https://en.cppreference.com/w/cpp/container/vector>`_
standard library. from the C++ standard library.
.. note:: .. note::
...@@ -338,8 +437,19 @@ standard library. ...@@ -338,8 +437,19 @@ standard library.
how many elements you are going to put in the vector. For more details how many elements you are going to put in the vector. For more details
see `this page from cppreference <https://en.cppreference.com/w/cpp/container/vector>`_. see `this page from cppreference <https://en.cppreference.com/w/cpp/container/vector>`_.
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_cpp.pyx .. tabs::
:linenos: .. group-tab:: Pure Python
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_cpp.py
:linenos:
.. include::
../cimport-warning
.. group-tab:: Cython
.. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_cpp.pyx
:linenos:
The first line is a compiler directive. It tells Cython to compile your code to C++. The first line is a compiler directive. It tells Cython to compile your code to C++.
This will enable the use of C++ language features and the C++ standard library. This will enable the use of C++ language features and the C++ standard library.
...@@ -357,4 +467,3 @@ Language Details ...@@ -357,4 +467,3 @@ Language Details
For more about the Cython language, see :ref:`language-basics`. For more about the Cython language, see :ref:`language-basics`.
To dive right in to using Cython in a numerical computation context, To dive right in to using Cython in a numerical computation context,
see :ref:`memoryviews`. see :ref:`memoryviews`.
...@@ -340,6 +340,8 @@ improve the type analysis in Cython. ...@@ -340,6 +340,8 @@ improve the type analysis in Cython.
Tips and Tricks Tips and Tricks
--------------- ---------------
.. _calling-c-functions:
Calling C functions Calling C functions
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
......
docs/src/tutorial/python_division.png

7.97 KB | W: | H:

docs/src/tutorial/python_division.png

73.3 KB | W: | H:

docs/src/tutorial/python_division.png
docs/src/tutorial/python_division.png
docs/src/tutorial/python_division.png
docs/src/tutorial/python_division.png
  • 2-up
  • Swipe
  • Onion skin
This page uses two different syntax variants: the Cython specific ``cdef`` syntax
and static Cython type declarations in
:ref:`pure Python code <pep484_type_annotations>`,
following `PEP-484 <https://www.python.org/dev/peps/pep-0484/>`_ type hints
and `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_ variable annotations.
To make good use of the latter, including C data types, etc., you need
the special ``cython`` module, which you can import with
.. code-block:: python
import cython
in the Python module that you want to compile.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment