You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Cython中声明列表的列表?附相关.pyx代码示例

在Cython中声明列表的列表的几种方法

嘿,我来结合你的代码片段,聊聊Cython里怎么处理嵌套列表(列表的列表)~你的现有写法是可行的,但我们可以根据性能需求选择不同的实现方式:

1. 你当前的Python风格写法(简单但性能一般)

你用的是Python原生的列表推导:

z = [[0]*(n+1) for _ in range(n*(2*n-1))]

这种写法在Cython里完全能运行,但本质上还是Python list对象的嵌套,每次访问元素都会有Python层面的类型检查和开销,适合快速开发但对性能要求不高的场景。

2. 添加类型注解的Python列表(小幅度提升性能)

如果想在保留Python列表灵活性的同时提升一点性能,可以用Cython 3.0+支持的泛型列表类型注解,明确指定嵌套列表的元素类型:

def f(m):
    cdef int n = len(m)//2  # 建议用//做整数除法,避免浮点数
    cdef list[list[int]] z  # 声明z是int类型的嵌套列表
    z = [[0]*(n+1) for _ in range(n*(2*n-1))]
    # ... 后续代码不变

这样Cython会在编译时做类型优化,访问z[i][j]时的开销会比无注解的Python列表小一些。

3. C风格二维数组(性能最优,手动管理内存)

如果你的场景对性能要求极高,推荐用C层面的二维数组,完全绕开Python对象的开销。需要注意要手动分配和释放内存:

from libc.stdlib cimport malloc, free

@cython.boundscheck(False)
@cython.cdivision(True)
@cython.wraparound(False)
def f(m):
    cdef int n = len(m)//2
    cdef int j, k
    cdef int rows = n*(2*n-1)
    cdef int cols = n+1
    # 分配二维数组
    cdef int **z = <int**>malloc(rows * sizeof(int*))
    for j in range(rows):
        z[j] = <int*>malloc(cols * sizeof(int))
        # 初始化子数组为0
        for k in range(cols):
            z[j][k] = 0
    
    # 你的业务逻辑
    for j in range(1, 2*n):
        for k in range(j):
            z[j*(j-1)//2 + k][0] = m[j][k]
    
    # 调用solve前可以把C数组转成Python列表(如果solve需要Python列表的话)
    # 或者修改solve的参数为C数组类型
    result = solve(z, 2*n, 1, [1] + [0]*n, n)
    
    # 释放内存!一定要记得,否则会泄漏
    for j in range(rows):
        free(z[j])
    free(z)
    
    return result

这种方式访问元素的速度和纯C一样快,但需要仔细管理内存,避免泄漏。

4. Cython内存视图(安全且高性能)

如果不想手动管理内存,又想接近C数组的性能,推荐用Cython内存视图,它是类型安全的,自动管理内存,还能和Python列表互相转换:

from cython.view cimport array as cvarray

@cython.boundscheck(False)
@cython.cdivision(True)
@cython.wraparound(False)
def f(m):
    cdef int n = len(m)//2
    cdef int j, k
    cdef int rows = n*(2*n-1)
    cdef int cols = n+1
    # 创建int类型的二维内存视图,初始化为0
    cdef int[:, :] z = cvarray(shape=(rows, cols), itemsize=sizeof(int), format="i")
    z[:, :] = 0  # 批量初始化所有元素为0
    
    # 访问方式和Python列表类似,但速度快很多
    for j in range(1, 2*n):
        for k in range(j):
            z[j*(j-1)//2 + k][0] = m[j][k]
    
    # 如果solve需要Python列表,可以把内存视图转成列表:
    z_py = [list(row) for row in z]
    result = solve(z_py, 2*n, 1, [1] + [0]*n, n)
    
    return result

内存视图的访问性能接近C数组,而且不用手动释放内存,非常适合大多数性能敏感的场景。

针对你代码里的solve函数的小建议

你在solve里用了c = [b[(j+1)*(j+2)//2+k+2][:] for j in range(1, s-2) for k in range(j)],同样可以把b改成内存视图或者C数组,来提升循环内的访问速度。

内容的提问来源于stack exchange,提问作者Simd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:46:37