如何预分配列表的列表?

12 投票
4 回答
11668 浏览
提问于 2025-04-16 13:56

我正在用这段代码创建一个列表的列表:

zeroArray = [0]*Np
zeroMatrix = []
for i in range(Np):
    zeroMatrix.append(zeroArray[:])

有没有更有效的方法来做到这一点?我希望能找到类似于 zeroArray = [0]*Np; zeroMat = zeroArray*Np 这样的写法,但我找不到类似的东西。

4 个回答

5

这样做可能会稍微高效一些:

zeroArray = [0]*Np
zeroMatrix = [None] * Np
for i in range(Np):
    zeroMatrix[i] = zeroArray[:]

你真正想要的方式可能不会像你希望的那样工作。这是因为如果你用 * 创建了 Np 个列表元素的副本,你得到的其实是 Np 个指向同一个东西的引用。对于数字 0 来说,这没什么大不了的,因为你加任何东西都会得到一个新数字。但对于列表来说,你会得到一个矩阵,一旦你改变了某一行的任何元素,整列都会跟着一起改变。

这种方法是到目前为止提到的第二快的:

$ python3 -m timeit -s 'Np = 80' 'zeroArray = [0]*Np
zeroMatrix = [None] * Np
for i in range(Np):
    zeroMatrix[i] = zeroArray[:]'
10000 loops, best of 3: 72.8 usec per loop

$ python3 -m timeit -s 'Np = 80' 'zeroMatrix = [[0] * Np for i in range(Np)]'
10000 loops, best of 3: 85 usec per loop

$ python3 -m timeit -s 'Np = 80' 'zeroMatrix = [[0 for _ in range(Np)] for _ in range(Np)]'
1000 loops, best of 3: 566 usec per loop

我无法自己测试基于numpy的解决方案,因为我系统上没有Python3的numpy包。不过可以肯定的是,它的速度快得多。

11

也许你可以考虑使用 NumPy。看起来你在做一些数字计算,而这正是它的强项。到目前为止,这是最快的,下面的代码不包括导入的那一行:

import numpy
Np = 80
zeroMatrix = numpy.zeros((Np, Np))

时间:

>python -m timeit -s "import numpy; Np = 80" "zeroMatrix = numpy.zeros((Np, Np))"
100000 loops, best of 3: 4.36 usec per loop

>python -m timeit -s "Np = 80" "zeroArray = [0]*Np" "zeroMatrix = [None] * Np" "for i in range(Np):" "  zeroMatrix[i] = zeroArray[:]"
10000 loops, best of 3: 62.5 usec per loop

>python -m timeit -s "Np = 80" "zeroMatrix = [[0] * Np for i in range (Np)]"
10000 loops, best of 3: 77.5 usec per loop

>python -m timeit -s "Np = 80" "zeroMatrix = [[0 for _ in range(Np)] for _ in range(Np)]"
1000 loops, best of 3: 474 usec per loop
10

你可以这样做:

zeroMatrix = [[0] * Np for i in range(Np)]

更新:如果我们要把这个当成比赛来进行的话,我发现了一种比Omnifarious的方法更快(在我的电脑上)。当然,这个速度比不上numpy;不过这都是学术讨论,对吧?毕竟我们在讨论的是微秒级别的事情。

我觉得这个方法有效是因为它避免了使用append而且也避免了预先分配zeroMatrix

zeroArray = [0] * Np
zeroMatrix = [zeroArray[:] for i in range(Np)]

我的测试结果:

$ python -m timeit -s "Np = 80" "zeroMatrix = [[0] * Np for i in range(Np)]"
1000 loops, best of 3: 200 usec per loop
$ python -m timeit -s "Np = 80" "zeroArray = [0] * Np" "zeroMatrix = [None] * Np" "for i in range(Np):" "    zeroMatrix[i] = zeroArray[:]"
10000 loops, best of 3: 171 usec per loop
$ python -m timeit -s "Np = 80" "zeroArray = [0] * Np" "zeroMatrix = [zeroArray[:] for i in range(Np)]"
10000 loops, best of 3: 165 usec per loop

撰写回答