Introduction to Pyrex http www sweetapp compyrex September

Introduction to Pyrex http: //www. sweetapp. com/pyrex September 2002 • Brian Quinlan • brian@sweetapp. com

What is Pyrex? • Pyrex is a language for writing Python extension modules • Pyrex has a Python-like syntax that gets compiled into C code • Pyrex let’s you mix Python and C data types and function calls freely Slide 2 © 2002 Brian Quinlan

The perfect example • Let’s compute perfect numbers! • Perfect numbers are number whose positive divisors (except for itself) sum to itself e. g. 6 is a perfect number because: 1 x 6=6 2 x 3=6 1+2+3=6 • Naïve methods of computing perfect numbers are slow – so let’s use one and optimize Slide 3 © 2002 Brian Quinlan

The Python code from math import sqrt, ceil from operator import add def _calculate_factors(x): factors = [1] sqrt_x = int(ceil(sqrt(x))) for i in xrange(2, sqrt_x): if x % i == 0: factors. append(i) factors. append(x / i) if sqrt_x ** 2 == x: factors. append(sqrt_x) return factors def is_perfect(x): return reduce(add, _calculate_factors(x), 0) == x Slide 4 © 2002 Brian Quinlan

The Pyrex code from math import sqrt, ceil from operator import add def _calculate_factors(x): factors = [1] sqrt_x = int(ceil(sqrt(x))) for i in xrange(2, sqrt_x): if x % i == 0: factors. append(i) factors. append(x / i) if sqrt_x ** 2 == x: factors. append(sqrt_x) return factors def is_perfect(x): return reduce(add, _calculate_factors(x), 0) == x Slide 5 © 2002 Brian Quinlan

Pyrex is VERY like Python • Pyrex syntax is VERY similar to Python syntax • Running the same code using Pyrex is about 15% faster • There are Pyrex-specific features that allow us to improve the performance even more Slide 6 © 2002 Brian Quinlan

Use C types from math import sqrt, ceil from operator import add def _calculate_factors(int x): cdef int sqrt_x, i factors = [1] sqrt_x = ceil(sqrt(x)) for i in xrange(2, sqrt_x): if x % i == 0: factors. append(i) factors. append(x / i) if sqrt_x ** 2 == x: factors. append(sqrt_x) return factors def is_perfect(int x): return reduce(add, _calculate_factors(x), 0) == x Slide 7 © 2002 Brian Quinlan

Use a Pyrex “for” construct from math import sqrt, ceil from operator import add def _calculate_factors(int x): cdef int sqrt_x, i factors = [1] sqrt_x = ceil(sqrt(x)) for i from 2 <= i < sqrt_x: if x % i == 0: factors. append(i) factors. append(x / i) if sqrt_x ** 2 == x: factors. append(sqrt_x) return factors def is_perfect(int x): return reduce(add, _calculate_factors(x), 0) == x Slide 8 © 2002 Brian Quinlan

Use the C math library cdef extern from "math. h": double sqrt(double x) double ceil(double x) from operator import add def _calculate_factors(int x): cdef int sqrt_x, i factors = [1] sqrt_x = ceil(sqrt(x)) for i from 2 <= i < sqrt_x: if x % i == 0: factors. append(i) factors. append(x / i) … Slide 9 © 2002 Brian Quinlan

Use C functions cdef extern from "math. h": … from operator import add cdef object _calculate_factors(int x): cdef int sqrt_x, i factors = [1] sqrt_x = ceil(sqrt(x)) for i from 2 <= i < sqrt_x: if x % i == 0: factors. append(i) factors. append(x / i) if sqrt_x ** 2 == x: factors. append(sqrt_x) return factors … Slide 10 © 2002 Brian Quinlan

Do our own summation … def is_perfect(int x): cdef int sum cdef int i sum = 0 for i in _calculate_factors(x): sum = sum + i return sum == x Slide 11 © 2002 Brian Quinlan

Results Slide 12 © 2002 Brian Quinlan

A vector class cdef class Vector 3: cdef double x cdef double y cdef double z def __init__(self, double x, double y, double z): self. x, self. y, self. z = x, y, z Slide 13 © 2002 Brian Quinlan

Getting it’s attributes def __getattr__(self, name): if name == 'x': return self. x elif name == 'y': return self. y elif name == 'z': return self. z else: raise Attribute. Error( 'Vector 3 has no attribute "%s"' % name ) Slide 14 © 2002 Brian Quinlan

Some operations def __add__(Vector 3 a, Vector 3 b): return Vector 3(a. x + b. x, a. y + b. y, a. z + b. z) cdef int __nonzero__(Vector 3 self): return self. x or self. y or self. z def __str__(self): return 'Vector 3(x=%s, y=%s, z=%s)' % ( self. x, self. y, self. z) def __repr__(self): # __repr__ = __str__ not allowed return 'Vector 3(x=%r, y=%r, z=%r)' % ( self. x, self. y, self. z) Slide 15 © 2002 Brian Quinlan

Using Pyrex • The hassle-factor is low (easy to install Pyrex, easy to get Pyrex to compile your code - so long as you have a C compiler) • Documentation is minimal but understandable • Writing simple functions using Pyrex features is easy (though there a few gotchas) • Writing classes is harder (more gotches, more bugs, more unfinished features) • C and the Python C API has more gotches than Pyrex Slide 16 © 2002 Brian Quinlan
- Slides: 16