def primes_python(nb_primes):
p = []
n = 2
while len(p) < nb_primes:
# Is n prime?
for i in p:
if n % i == 0:
break
# If no break occurred in the loop
else:
p.append(n)
n += 1
return p
使用Cython直接转换python代码
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize(['primes.pyx', # Cython code file with primes() function
'primes_py.py'], # Python code file with primes_python_compiled() function
annotate=True), # enables generation of the html annotation file
)
对比cython代码和直接转换python代码的结果是否一致
import random
from libc.stdlib cimport malloc, free
def random_noise(int number=1):
cdef int i
# allocate number * sizeof(double) bytes of memory
cdef double *my_array = <double *> malloc(number * sizeof(double))
if not my_array:
raise MemoryError()
try:
ran = random.normalvariate
for i in range(number):
my_array = ran(0, 1)
# ... let's just assume we do some more heavy C calculations here to make up
# for the work that it takes to pack the C double values into Python float
# objects below, right after throwing away the existing objects above.
return [x for x in my_array[:number]]
finally:
# return the previously allocated memory to the system
free(my_array)
使用cython封装的api PyMem_Malloc, PyMem_Realloc, PyMem_Free 同样功能实现
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
大块并长长生命周期的内存可以同上例使用 try..finally 块来控制。另一种比较好的方式时通过python 对象的运行时内存管理来控制,简单用例如下,在对象创建时申请内存,回收时释放内存。
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
cdef class SomeMemory:
cdef double* data
def __cinit__(self, size_t number):
# allocate some memory (uninitialised, may contain arbitrary data)
self.data = <double*> PyMem_Malloc(number * sizeof(double))
if not self.data:
raise MemoryError()
def resize(self, size_t new_number):
# Allocates new_number * sizeof(double) bytes,
# preserving the current content and making a best-effort to
# re-use the original data location.
mem = <double*> PyMem_Realloc(self.data, new_number * sizeof(double))
if not mem:
raise MemoryError()
# Only overwrite the pointer if the memory was really reallocated.
# On error (mem is NULL), the originally memory has not been freed.
self.data = mem
def __dealloc__(self):
PyMem_Free(self.data) # no-op if self.data is NULL
7.使用动态数组
一个计算编辑距离的例子
cdef int** dp = <int**> malloc((len1 + 1) * sizeof(int*))
for i in range(len1 + 1):
dp = <int*> malloc((len2 + 1) * sizeof(int))
for i in range(len1 + 1):
dp[0] = i
for j in range(len2 + 1):
dp[0][j] = j
for i in range(1, len1 + 1):
for j in range(1, len2 + 1):
delta = 0 if word1[i - 1] == word2[j - 1] else 1
dp[j] = min(dp[i - 1][j - 1] + delta, min(dp[i - 1][j] + 1, dp[j - 1] + 1))
cdef result = dp[len1][len2]
for i in range(len1 + 1):
free(dp)
free(dp)