这就涉及到CPython源码了
[[]] * 3复制的是[]的指针, 在CPython底层里面这个指针被重复复制了, 也就是说, 这里复制得到的a[0], a[1], a[2]其实是同一个指针, 一个变了当然剩下的跟着变
第二处的[]是for循环内的局部变量, 每次都不一样
贴一段实现[[]] * 3的CPython源码, 可以看到第一个while循环里面把同一个指针复制了n遍
list_repeat(PyListObject *a, Py_ssize_t n)
{
Py_ssize_t size;
PyListObject *np;
if (n < 0)
n = 0;
if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n)
return PyErr_NoMemory();
size = Py_SIZE(a) * n;
if (size == 0)
return PyList_New(0);
np = (PyListObject *) list_new_prealloc(size);
if (np == NULL)
return NULL;
PyObject **dest = np->ob_item;
PyObject **dest_end = dest + size;
if (Py_SIZE(a) == 1) {
PyObject *elem = a->ob_item[0];
Py_SET_REFCNT(elem, Py_REFCNT(elem) + n);
#ifdef Py_REF_DEBUG
_Py_RefTotal += n;
#endif
while (dest < dest_end) {
*dest++ = elem;
}
}
else {
PyObject **src = a->ob_item;
PyObject **src_end = src + Py_SIZE(a);
while (src < src_end) {
Py_SET_REFCNT(*src, Py_REFCNT(*src) + n);
#ifdef Py_REF_DEBUG
_Py_RefTotal += n;
#endif
*dest++ = *src++;
}
// Now src chases after dest in the same buffer
src = np->ob_item;
while (dest < dest_end) {
*dest++ = *src++;
}
}
Py_SET_SIZE(np, size);
return (PyObject *) np;
}
前者定义的是 x[0] = x[1] = x[2] = [],用的是同一地址
后者定义的是 x[0], x[1], x[2] = [], [], [],不同地址
第一题创建的是列表的浅拷贝,二维列表里的三个空列表,都是指向同一个内存地址。所以看似三个列表,其实只有一个。
第二题创建的三个空列表是相互独立的