如何使用PyObjects数组扩展Python列表

时间:2017-02-09 04:28:18

标签: python performance python-c-api

我正在尝试处理一个返回PyObject数组的API,我想extend一个现有的python list及其内容。

到目前为止,我只是追加数组中的每一项:

static PyObject *
myfunc(PyObject *module, PyObject *alist, PyObject **items, Py_ssize_t arrsize)
{
    Py_ssize_t i;
    for (i = 0 ; i < arrsize; i++) {
        if (PyList_Append(alist, items[i]) == -1) {
            return NULL;
        }
    }
    return alist;
}

但是列表或多或少只是array of PyObjects本身的包装器。

那么有更好(或更快)的方式来扩展该列表吗?我没有在Python-C-API中找到一个函数,并且考虑到PyList_Object的过度分配,创建一个新数组似乎很麻烦,然后memcpy原始数组,然后将其分配给{{ 1}}。

1 个答案:

答案 0 :(得分:2)

您的意图是实施或使用list.extend(),但

l.extend(items)

等同于

l[len(l):] = items

这可以在python c api PyList_SetSlice本身内完成,尽管你会有创建新列表的开销。但它比每次追加调整列表大小更好。

static PyObject *
myfunc(PyObject *module, PyObject *alist, PyObject **items, Py_ssize_t arrsize)
{
    Py_ssize_t i, len = PyList_GET_SIZE(alist);
    PyObject *l = PyList_New(arrsize);
    int r = PyList_SetSlice(alist, len, len + arrsize, l);
    Py_CLEAR(l);
    if (r == -1) {
        return NULL;
    }

    for (i = 0 ; i < arrsize; i++) {
        Py_INCREF(items[i]);
        PyList_SET_ITEM(alist, len + i, items[i]);
    }
    return Py_INCREF(alist), alist;
}

另外,你在退货时丢失了参考资料。