Cython,有没有办法只创建一种类型的列表? (与Python列表不同)

时间:2011-08-09 13:43:39

标签: python list cython

在我的Group课程中,必须有一个属性particles,该属性应该是类似但可调整大小的类型,可以保持Particle - 实例
。 使用Group声明Particlecdef这两个类。

由于Python列表可以携带任何Python对象,我认为可能有一种更高效的方式来声明某种只接受Particle - 实例的C列表。 在C中,我会想到List<Particle> particle = new List<Particle>();

Cython是否有任何等价物,或者我应该继续使用Python列表?

4 个答案:

答案 0 :(得分:2)

我不确定你是否会获得任何表现,但如果你想确保该列表只包含某些类型的数据......

class Group(Object):
    #...
    def isParticle(self, p):
        return hasattr(p, "anAttributeOnlyParticlesHave")
    def getPartiles(self):
        return filter(self.isParticle, self._Particles)
    def setParticles(self, newParticles):
        self._Particles = filter(self.isParticle, newParticles)
    particles = property(getParticles, setParticles)

同样,这不是太快,但它是你问题的直接答案。

你可能会通过写一个C模块获得一些东西 - 我不确定。如果你真的需要表现,你使用的是错误的语言。

通常,使用Python,典型的速度噱头不起作用。有足够的缓存和优化正在进行,你通常不会通过思考C语言来获得很多 - 除非你正在编写C模块。

答案 1 :(得分:2)

是的,您只需使用cpp中的相同矢量类:

from libcpp.vector cimport vector

cdef class Item:
    cdef int amount
    cdef str description

def allocate():
    cdef vector[Item] bunch_of_items
    for i in xrange(100):
        bunch_of_items.push_back(Item())

编译:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext


ext = Extension(
    "extension_name",            
    ["module_name.pyx", ],     
    language="c++",         
    libraries=["stdc++"],
    cmdclass = {'build_ext': build_ext}
    )

setup(
    name = "name",
    cmdclass = {"build_ext": build_ext},
    ext_modules = [ext]
)

请记住,除非将其转换为python列表,否则无法将此向量列表传递回python。

答案 2 :(得分:1)

问题有待提出:你为什么要这样?

  • 是为了提高效率(在阵列上循环)还是为了降低内存占用量?
  • 你需要一个数组或链表就够了吗?
  • 你的粒子类是一个简单的结构还是具有行为/方法的东西?

根据这些,最好的解决方案是使用python数组到numpy或stl容器。

(注意,例如,在cython中循环遍历python列表可能非常有效。)

答案 3 :(得分:0)

您可以将链接列表写为cython结构。我已将val的类型设置为int,但您可以将其设置为任何结构类型。

from cpython.mem cimport PyMem_Malloc

cdef struct link:
    int val
    link *next


cdef link * create_link(int v, link *prev_link):
    cdef link *x = <link *>PyMem_Malloc(sizeof(link))
    x.val = v
    x.next = NULL
    if prev_link is not NULL:
        prev_link.next = x
    return x

然后您可以创建一个指向动态分配的链接对象的指针。

cpdef many_links(int n):
    cdef link * l = NULL
    cdef link * f = NULL # keeps track of the first elem in the list 

    for i in range(n):
        l = create_link(i, l)
        if f == NULL:
            f = l

    # Write out the linked list to a python list
    cdef list r = []
    c = f
    while c.next != NULL:
        r.append(c.val)
        c = c.next
    r.append(c.val)

    return r