160 likes | 294 Views
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
E N D
Introduction to Pyrexhttp://www.sweetapp.com/pyrexSeptember 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
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
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
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
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
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
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
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) …
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 …
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
A vector class cdef class Vector3: 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
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 AttributeError( 'Vector3 has no attribute "%s"' % name )
Some operations def __add__(Vector3 a, Vector3 b): return Vector3(a.x + b.x, a.y + b.y, a.z + b.z) cdef int __nonzero__(Vector3 self): return self.x or self.y or self.z def __str__(self): return 'Vector3(x=%s, y=%s, z=%s)' % ( self.x, self.y, self.z) def __repr__(self): # __repr__ = __str__ not allowed return 'Vector3(x=%r, y=%r, z=%r)' % ( self.x, self.y, self.z)
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 are 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