Pyrex 和 NumPy

日期2008-04-09(最后修改),2006-01-06(创建)

请注意,这里描述的代码略微过时,因为今天 cython 是 Pyrex 的积极维护版本,并且 numpy 现在附带 Cython 示例。

与其维护 wiki 和源代码目录,我们将在 这里 继续更新源代码。

旧的 Pyrex 页面

Pyrex 是一种用于编写 Python C 扩展的语言。它的语法与编写 Python 非常相似。一个文件被编译成一个文件,然后像标准的 Python C 扩展模块一样进行编译。许多人发现使用 Pyrex 编写扩展模块比用 C 编写或使用其他工具(如 SWIG)更可取。

此页面是使用 Pyrex 本地访问 numpy 数组的起点。请注意,在当前版本的 NumPy(SVN)中,该目录包含一个完整的示例,其中包含此页面中的代码,包括一个适当的文件,以便您可以使用标准的 Python 机制安装它。这将帮助您快速入门。

这是一个名为“c_python.pxd”的文件

In [ ]
cdef extern from "Python.h":
    ctypedef int Py_intptr_t

这是一个名为“c_numpy.pxd”的文件

In [ ]
cimport c_python

cdef extern from "numpy/arrayobject.h":
    ctypedef class numpy.ndarray [object PyArrayObject]:
        cdef char *data
        cdef int nd
        cdef c_python.Py_intptr_t *dimensions
        cdef c_python.Py_intptr_t *strides
        cdef object base
        # descr not implemented yet here...
        cdef int flags
        cdef int itemsize
        cdef object weakreflist

    cdef void import_array()

这是一个示例程序,将其命名为类似“test.pyx”的后缀。

In [ ]
cimport c_numpy
cimport c_python
import numpy

c_numpy.import_array()

def print_array_info(c_numpy.ndarray arr):
    cdef int i

    print '-='*10
    print 'printing array info for ndarray at 0x%0lx'%(<c_python.Py_intptr_t>arr,)
    print 'print number of dimensions:',arr.nd
    print 'address of strides: 0x%0lx'%(<c_python.Py_intptr_t>arr.strides,)
    print 'strides:'
    for i from 0<=i<arr.nd:
        # print each stride
        print '  stride %d:'%i,<c_python.Py_intptr_t>arr.strides[i]
    print 'memory dump:'
    print_elements( arr.data, arr.strides, arr.dimensions, arr.nd, sizeof(double), arr.dtype )
    print '-='*10
    print

cdef print_elements(char *data,
                    c_python.Py_intptr_t* strides,
                    c_python.Py_intptr_t* dimensions,
                    int nd,
                    int elsize,
                    object dtype):
    cdef c_python.Py_intptr_t i,j
    cdef void* elptr

    if dtype not in [numpy.dtype(numpy.object_),
                     numpy.dtype(numpy.float64)]:
        print '   print_elements() not (yet) implemented for dtype %s'%dtype.name
        return

    if nd ==0:
        if dtype==numpy.dtype(numpy.object_):
            elptr = (<void**>data)[0] #[0] dereferences pointer in Pyrex
            print '  ',<object>elptr
        elif dtype==numpy.dtype(numpy.float64):
            print '  ',(<double*>data)[0]
    elif nd == 1:
        for i from 0<=i<dimensions[0]:
            if dtype==numpy.dtype(numpy.object_):
                elptr = (<void**>data)[0]
                print '  ',<object>elptr
            elif dtype==numpy.dtype(numpy.float64):
                print '  ',(<double*>data)[0]
            data = data + strides[0]
    else:
        for i from 0<=i<dimensions[0]:
            print_elements(data, strides+1, dimensions+1, nd-1, elsize, dtype)
            data = data + strides[0]

def test():
    """this function is pure Python"""
    arr1 = numpy.array(-1e-30,dtype=numpy.Float64)
    arr2 = numpy.array([1.0,2.0,3.0],dtype=numpy.Float64)

    arr3 = numpy.arange(9,dtype=numpy.Float64)
    arr3.shape = 3,3

    four = 4
    arr4 = numpy.array(['one','two',3,four],dtype=numpy.object_)

    arr5 = numpy.array([1,2,3]) # int types not (yet) supported by print_elements

    for arr in [arr1,arr2,arr3,arr4,arr5]:
        print_array_info(arr)

现在,如果您编译并安装上面的 test.pyx,的输出应该类似于以下内容

In [ ]
-=-=-=-=-=-=-=-=-=-=
printing array info for ndarray at 0x8184508
print number of dimensions: 0
address of strides: 0xb764f7ec
strides:
memory dump:
   -1e-30
-=-=-=-=-=-=-=-=-=-=

-=-=-=-=-=-=-=-=-=-=
printing array info for ndarray at 0x8190060
print number of dimensions: 1
address of strides: 0x818453c
strides:
  stride 0: 8
memory dump:
   1.0
   2.0
   3.0
-=-=-=-=-=-=-=-=-=-=

-=-=-=-=-=-=-=-=-=-=
printing array info for ndarray at 0x82698a0
print number of dimensions: 2
address of strides: 0x8190098
strides:
  stride 0: 24
  stride 1: 8
memory dump:
   0.0
   1.0
   2.0
   3.0
   4.0
   5.0
   6.0
   7.0
   8.0
-=-=-=-=-=-=-=-=-=-=

-=-=-=-=-=-=-=-=-=-=
printing array info for ndarray at 0x821d6e0
print number of dimensions: 1
address of strides: 0x818ed74
strides:
  stride 0: 4
memory dump:
   one
   two
   3
   4
-=-=-=-=-=-=-=-=-=-=

-=-=-=-=-=-=-=-=-=-=
printing array info for ndarray at 0x821d728
print number of dimensions: 1
address of strides: 0x821d75c
strides:
  stride 0: 4
memory dump:
   print_elements() not (yet) implemented for dtype int32
-=-=-=-=-=-=-=-=-=-=

[http://pytables.sourceforge.net/ pytables 项目] 广泛使用 Pyrex 和 numarray。有关更多想法,请参阅 pytables 源代码。

= 另请参阅 = ["Cookbook/ArrayStruct_and_Pyrex"]

章节作者:AndrewStraw、DavidLinke、Unknown[137]、Unknown[25]、FernandoPerez