Python | Функция расширения, работающая с массивами
Давайте напишем функцию расширения C, которая может работать с непрерывными массивами данных, которые могут быть созданы модулем массива или библиотеками, такими как NumPy, и эта функция должна быть универсальной, а не специфичной для какой-либо одной библиотеки массивов.
The code should use Buffer Protocol to receive and process arrays in a portable manner. The code below is a C extension function that receives array data and calls the avg(double *buf, int len)
function from this article – Using C codes in Python.
Code #1 :
/* Call double avg(double *, int) */ static PyObject *py_avg(PyObject *self, PyObject *args) { PyObject *bufobj; Py_buffer view; double result; /* Get the passed Python object */ if (!PyArg_ParseTuple(args, "O" , &bufobj)) { return NULL; } /* Attempt to extract buffer information from it */ if (PyObject_GetBuffer(bufobj, &view, PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) == -1) { return NULL; } if (view.ndim != 1) { PyErr_SetString(PyExc_TypeError, "Expected a 1-dimensional array" ); PyBuffer_Release(&view); return NULL; } /* Check the type of items in the array */ if ( strcmp (view.format, "d" ) != 0) { PyErr_SetString(PyExc_TypeError, "Expected an array of doubles" ); PyBuffer_Release(&view); return NULL; } /* Pass the raw buffer and size to the C function */ result = avg(view.buf, view.shape[0]); /* Indicate we"re done working with the buffer */ PyBuffer_Release(&view); return Py_BuildValue( "d" , result); } |
Code #2 : How this extension function works
import array print ( "Average : " , avg(array.array( "d" , [ 1 , 2 , 3 ]))) import numpy print ( "Average numpy array : " , avg(numpy.array([ 1.0 , 2.0 , 3.0 ]))) print ( "Average list :
" , avg([ 1 , 2 , 3 ])) |
Output :
Average : 2.0 Average numpy array : 2.0
Average list : Traceback (most recent call last): File "", line 1, in TypeError: "list" does not support the buffer interface
PyBuffer_GetBuffer()
function is the key to the code in the article.- It tries to obtain the information about the memory representation in the given arbitrary Python object.
- It simply raises an exception and returns -1, if it is not possible to obtain information (as is the case with normal Python objects).
- The special flags passed to
PyBuffer_GetBuffer()
give additional hints about the kind of memory buffer that is requested. - As, PyBUF_ANY_CONTIGUOUS specifies that a contiguous region of memory is required.
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.