<p>注意,您正在做两件不同的事情。您打算使用:</p>
<pre><code>[[None] * n for _ in range(n)]
</code></pre>
<p>您已经将内部列表包装在一个额外的列表中,但这不会对计时结果产生很大影响。列表重复版本肯定更快</p>
<p><code>[None]*n</code>非常快,它精确地分配底层缓冲区,然后执行C级循环<code>[None for _ in range(n)]</code>是一个使用append的python级循环,append是按固定时间摊销的,但会涉及缓冲区重新分配</p>
<p>只需查看字节码就可以给出一个提示:</p>
<pre><code>>>> import dis
>>> dis.dis('[None]*n')
1 0 LOAD_CONST 0 (None)
2 BUILD_LIST 1
4 LOAD_NAME 0 (n)
6 BINARY_MULTIPLY
8 RETURN_VALUE
</code></pre>
<p>基本上,所有的工作都是在{<cd3>}中完成的。对于列表理解:</p>
<pre><code>>>> dis.dis("[None for _ in range(n)]")
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x7fc06e31bea0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (range)
8 LOAD_NAME 1 (n)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x7fc06e31bea0, file "<dis>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (_)
8 LOAD_CONST 0 (None)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE
>>>
</code></pre>
<p>循环工作是在Python解释器级别完成的。此外,它通过<code>.append</code>来增长列表,这在算法上是有效的,但仍然比列表重复所做的要慢,列表重复都被推到C层中</p>
<p>以下是C源代码:</p>
<p><a href="https://github.com/python/cpython/blob/48ed88a93bb0bbeaae9a4cfaa533e4edf13bcb51/Objects/listobject.c#L504" rel="nofollow noreferrer">https://github.com/python/cpython/blob/48ed88a93bb0bbeaae9a4cfaa533e4edf13bcb51/Objects/listobject.c#L504</a></p>
<p>如您所见,它将底层缓冲区分配到所需的确切大小:</p>
<pre><code>np = (PyListObject *) PyList_New(size);
</code></pre>
<p>然后,它执行快速循环,在不重新分配的情况下填充缓冲区。最普遍的情况是:</p>
<pre><code>p = np->ob_item;
items = a->ob_item;
for (i = 0; i < n; i++) {
for (j = 0; j < Py_SIZE(a); j++) {
*p = items[j];
Py_INCREF(*p);
p++;
}
}
</code></pre>