我们可以在 Cython 中创建 Python 对象的 C 数组吗?

问题描述 投票:0回答:1

我们可以在 Cython 中创建 Python 对象的 C 数组吗?

让我们考虑以下代码:

class C:                                                                                                                                                                                            
    pass                                                                                                                                                                                            
                                                                                                                                                                                                    
cdef object f():                                                                                                                                                                                    
    return C()

cdef void g(unsigned n):
    cdef object obj0 = f()
    cdef object obj1 = f()
    cdef object obj2 = f()
    cdef object obj3 = f()

有没有一种方法可以将各种对象存储在一个数组中,而不是使用多个变量?类似的东西:

cdef void g(unsigned n):
    cdef object[N_MAX] obj
    for i in range(n)
       obj[i] = f()
cython
1个回答
0
投票

实际上不可能创建一个

object
的数组。一个警告是,如果可以的话,我们应该使用
Py_INCREf
/
Py_DECREF
手动管理对象的生命周期。

最简单和最安全的举动可能是在 Python 层维护对象列表。按照原始问题中给出的示例,例如,我们可以使用列表理解:

cdef void g(unsigned n):                                                                                                                                                                            
    l = [f() for _ in range(n)]

    #...

这被编译成以下内容:

  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_v_n;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v__ = __pyx_t_3;
    __pyx_t_4 = __pyx_f_1a_f(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 10, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) __PYX_ERR(0, 10, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  }
  __pyx_v_l = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;

我很想使用 PyList_NewPyList_SET_ITEM 手动管理列表,以避免连续调用

__Pyx_ListComp_Append
:

from cpython cimport PyList_New, PyList_SET_ITEM, Py_INCREF
cdef void h(unsigned n):
    cdef object l = PyList_New(n)
    cdef unsigned i
    for i in range(n):
        o = f()
        Py_INCREF(o)
        PyList_SET_ITEM(l, i, o)

    #...

在实践中,这会大大降低代码的可读性(并且更容易出错),而好处微乎其微。

© www.soinside.com 2019 - 2024. All rights reserved.