Python | Функция расширения, работающая с массивами

Опубликовано: 12 Апреля, 2022

Давайте напишем функцию расширения 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. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.