列表添加元素,列表的重复

img


我请问一下这两个问题区别在哪里?为什么列表的重复*,和列表循环range,在这儿不同

这就涉及到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] = [], [], [],不同地址

第一题创建的是列表的浅拷贝,二维列表里的三个空列表,都是指向同一个内存地址。所以看似三个列表,其实只有一个。
第二题创建的三个空列表是相互独立的