Commit 21675932 authored by ggellner@encolpuis's avatar ggellner@encolpuis

Refactored some source includes. Changed the overview to be shorter and give...

Refactored some source includes. Changed the overview to be shorter and give credit to pyrex more prominantly. Added documentation to automatic range() conversion
parent e87f8344
...@@ -292,24 +292,37 @@ Keep in mind that there are some differences in operator precedence between ...@@ -292,24 +292,37 @@ Keep in mind that there are some differences in operator precedence between
Python and C, and that Cython uses the Python precedences, not the C ones. Python and C, and that Cython uses the Python precedences, not the C ones.
Integer for-loops Integer for-loops
----------------- ------------------
You should be aware that a for-loop such as:: You should be aware that a for-loop such as::
for i in range(n): for i in range(n):
... ...
won't be very fast, even if i and n are declared as C integers, because range won't be very fast if ``i`` is not a :keyword:`cdef` integer type.
is a Python function. For iterating over ranges of integers, Cython has another For iterating over ranges of integers, Cython has another form of for-loop::
form of for-loop::
for i from 0 <= i < n: for i from 0 <= i < n:
... ...
or::
for i from 0 <= i < n by s:
...
where ``s`` is some integer step size.
If the loop variable and the lower and upper bounds are all C integers, this If the loop variable and the lower and upper bounds are all C integers, this
form of loop will be much faster, because Cython will translate it into pure C form of loop will be much faster, because Cython will translate it into pure C
code. code.
.. note::
This is not necessary if ``i`` is a C integer type and ``n`` can be
determined at compile time. Just use the idiomatic :func:`range` loop, if
you are worried that the loop is not being converted correctly use the
annotate feature of the cython commandline (``-a``) to easily see the
generated C code. See :ref:`automatic-range-conversion`
Some things to note about the for-from loop: Some things to note about the for-from loop:
* The target expression must be a variable name. * The target expression must be a variable name.
...@@ -322,9 +335,6 @@ Some things to note about the for-from loop: ...@@ -322,9 +335,6 @@ Some things to note about the for-from loop:
Like other Python looping statements, break and continue may be used in the Like other Python looping statements, break and continue may be used in the
body, and the loop may have an else clause. body, and the loop may have an else clause.
.. note::
See :ref:`automatic-range-conversion`
Error return values Error return values
------------------- -------------------
...@@ -409,7 +419,10 @@ return value and raise it yourself, for example,:: ...@@ -409,7 +419,10 @@ return value and raise it yourself, for example,::
raise SpamError("Couldn't open the spam file") raise SpamError("Couldn't open the spam file")
The include statement The include statement
--------------------- ----------------------
.. warning::
This feature is deprecated. Use :ref:`sharing-declarations-label` instead.
A Cython source file can include material from other files using the include A Cython source file can include material from other files using the include
statement, for example:: statement, for example::
......
...@@ -6,61 +6,27 @@ ...@@ -6,61 +6,27 @@
Overview Overview
******** ********
A language for writing Python extension modules About Cython
==============
What is Cython all about? Cython is a language that makes writing C extensions for the Python language
========================= as easy as Python itself. Cython is based on the well-known `Pyrex
<http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_ language by Greg Ewing,
but supports more cutting edge functionality and optimizations [#]_.
The Cython language is very close to the Python language, but Cython
additionally supports calling C functions and declaring C types on variables
and class attributes. This allows the compiler to generate very efficient C
code from Cython code.
Cython is a language specially designed for writing Python extension modules. This makes Cython the ideal language for wrapping external C libraries,
It's designed to bridge the gap between the nice, high-level, easy-to-use and for fast C modules that speed up the execution of Python code.
world of Python and the messy, low-level world of C.
You may be wondering why anyone would want a special language for this. Python
is really easy to extend using C or C++, isn't it? Why not just write your
extension modules in one of those languages?
Well, if you've ever written an extension module for Python, you'll know that
things are not as easy as all that. First of all, there is a fair bit of
boilerplate code to write before you can even get off the ground. Then you're
faced with the problem of converting between Python and C data types. For the
basic types such as numbers and strings this is not too bad, but anything more
elaborate and you're into picking Python objects apart using the Python/C API
calls, which requires you to be meticulous about maintaining reference counts,
checking for errors at every step and cleaning up properly if anything goes
wrong. Any mistakes and you have a nasty crash that's very difficult to debug.
Various tools have been developed to ease some of the burdens of producing
extension code, of which perhaps SWIG is the best known. SWIG takes a
definition file consisting of a mixture of C code and specialised
declarations, and produces an extension module. It writes all the boilerplate
for you, and in many cases you can use it without knowing about the Python/C
API. But you need to use API calls if any substantial restructuring of the
data is required between Python and C.
What's more, SWIG gives you no help at all if you want to create a new
built-in Python type. It will generate pure-Python classes which wrap (in a
slightly unsafe manner) pointers to C data structures, but creation of true
extension types is outside its scope.
Another notable attempt at making it easier to extend Python is PyInline ,
inspired by a similar facility for Perl. PyInline lets you embed pieces of C
code in the midst of a Python file, and automatically extracts them and
compiles them into an extension. But it only converts the basic types
automatically, and as with SWIG, it doesn't address the creation of new
Python types.
Cython aims to go far beyond what any of these previous tools provides. Cython
deals with the basic types just as easily as SWIG, but it also lets you write
code to convert between arbitrary Python data structures and arbitrary C data
structures, in a simple and natural way, without knowing anything about the
Python/C API. That's right -- nothing at all! Nor do you have to worry about
reference counting or error checking -- it's all taken care of automatically,
behind the scenes, just as it is in interpreted Python code. And what's more,
Cython lets you define new built-in Python types just as easily as you can
define new classes in Python.
Future Plans Future Plans
============ ============
Cython is not finished. Substantial tasks remaining. See Cython is not finished. Substantial tasks remaining. See
:ref:`cython-limitations-label` for a current list. :ref:`cython-limitations-label` for a current list.
.. rubric:: Footnotes
.. [#] For differences with Pyrex see :ref:`pyrex-differences-label`.
.. highlight:: cython .. highlight:: cython
.. _pyrex-differences-label:
Differences between Cython and Pyrex Differences between Cython and Pyrex
==================================== ====================================
...@@ -17,20 +19,6 @@ a list. Also, use the :keyword:`for` ... :keyword:`from` syntax too, e.g.:: ...@@ -17,20 +19,6 @@ a list. Also, use the :keyword:`for` ... :keyword:`from` syntax too, e.g.::
[i*i for i from 0 <= i < 10] [i*i for i from 0 <= i < 10]
In-place operators
------------------
The following is now legal::
x += 10
for all single-character operators, for both python and :keyword:`cdef` variables. Side
effects behave properly, i.e. for::
L[foo()] += bar()
:func:`foo` is called exactly once, before :func:`bar`.
Conditional expressions "x if b else y" (python 2.5) Conditional expressions "x if b else y" (python 2.5)
---------------------------------------------------- ----------------------------------------------------
...@@ -168,13 +156,9 @@ See :ref:`early-binding-speed-label` for explanation and usage tips. ...@@ -168,13 +156,9 @@ See :ref:`early-binding-speed-label` for explanation and usage tips.
.. _automatic-range-conversion: .. _automatic-range-conversion:
(Optional) automatic range conversion Automatic range conversion
------------------------------------- -------------------------------------
::
$cython --convert-range
This will convert statements of the form ``for i in range(...)`` to ``for i This will convert statements of the form ``for i in range(...)`` to ``for i
from ...`` when ``i`` is any cdef'd integer type, and the direction (i.e. sign from ...`` when ``i`` is any cdef'd integer type, and the direction (i.e. sign
of step) can be determined. of step) can be determined.
......
...@@ -30,17 +30,15 @@ available to you -- even in the midst of manipulating C data. ...@@ -30,17 +30,15 @@ available to you -- even in the midst of manipulating C data.
Cython Hello World Cython Hello World
=================== ===================
As Cython can accept almost any valid plain python file (though see the As Cython can accept almost any valid python source file, one of the hardest
`exceptions`), one of the hardest things in getting started is just figuring things in getting started is just figuring out how to compile your extension.
out how to compile your file.
So lets start with the canonical python hello world:: So lets start with the canonical python hello world::
print "Hello World" print "Hello World"
So the first thing to do is rename the file to :file:`helloworld.pyx`. Now we So the first thing to do is rename the file to :file:`helloworld.pyx`. Now we
need to make the :file:`setup.py`, which is like a python Makefile if you are need to make the :file:`setup.py`, which is like a python Makefile.::
familiar.::
from distutils.core import setup from distutils.core import setup
from distutils.extension import Extension from distutils.extension import Extension
...@@ -55,42 +53,31 @@ To use this to build your Cython file use the commandline options:: ...@@ -55,42 +53,31 @@ To use this to build your Cython file use the commandline options::
$ python setup.py build_ext --inplace $ python setup.py build_ext --inplace
Which will leave a file in your local directory called `helloworld.so`. Now to Which will leave a file in your local directory called `helloworld.so` in unix
use this file start the python interpreter and:: or `helloworld.dll` in Windows. Now to use this file start the python
interpreter and simply import it as if it was a regular python module::
>>> import helloworld >>> import helloworld
"Hello World" "Hello World"
Congratulations! You know know how to build a Cython extension. But So Far Congratulations! You now know how to build a Cython extension. But So Far
this example doesn't really show us why we would even want to use Cython, so this example doesn't really give a feeling why one would ever want to use Cython, so
lets do a more realistic example. lets create a more realistic example.
Fibonacci Fun Fibonacci Fun
============== ==============
From the official Python tutorial a simple fibonacci function is defined as:: From the official Python tutorial a simple fibonacci function is defined as:
def fib(n): .. literalinclude:: ../examples/tutorial/fib1/fib.pyx
"""Print the Fibonacci series up to n."""
a, b = 0, 1
while b < n:
print b,
a, b = b, a + b
Now following the steps for the Hello World example we first rename the file 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 distutils.core import setup .. literalinclude:: ../examples/tutorial/fib1/setup.py
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("fib", ["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::
...@@ -111,28 +98,9 @@ them as a Python list. ...@@ -111,28 +98,9 @@ them as a Python list.
:file:`primes.pyx`: :file:`primes.pyx`:
.. sourcecode:: cython .. literalinclude:: ../examples/tutorial/primes/primes.pyx
:linenos: :linenos:
def primes(int kmax):
cdef int n, k, i
cdef int p[1000]
result = []
if kmax > 1000:
kmax = 1000
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
result.append(n)
n = n + 1
return result
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 ``kmax`` is declared to be of type ``int`` . This except that the parameter ``kmax`` 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
......
def fib(n):
"""Print the Fibonacci series up to n."""
a, b = 0, 1
while b < n:
print b,
a, b = b, a + b
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("fib", ["fib.pyx"])]
)
def primes(kmax):
result = []
if kmax > 1000:
kmax = 1000
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
result.append(n)
n = n + 1
return result
def primes(int kmax):
cdef int n, k, i
cdef int p[1000]
result = []
if kmax > 1000:
kmax = 1000
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
result.append(n)
n = n + 1
return result
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("primes", ["primes.pyx"])]
)
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