【问题标题】:Why does appending to one list also append to all other lists in my list of lists? [duplicate]Python列表追加行为[重复]
【发布时间】:2023-03-11 10:25:01
【问题描述】:

真的不知道如何提出问题...

假设我执行以下操作:

    >>> l = [[]]*2
    >>> l
    [[], []]
    >>> l[0].append(1)
    >>> l
    [[1], [1]]

为什么两个列表都附加了 1?

【问题讨论】:

标签: python list


【解决方案1】:

展示内存布局的差异:

listOfLists = [[]] * 3
listOfListsRange = [[] for i in range(0, 3)]

【讨论】:

    【解决方案2】:

    这是我初始化列表列表的方法。行变化最慢。

    nrows = 3; ncols = 5
    
    l_of_ls = [[0]*ncols for i in range(nrows )]
    
    for rix, r in enumerate(l_of_ls):
        for cix, c in enumerate(r):
            print rix, cix, 'val = ',c
    

    结果

    0 0 val =  0
    0 1 val =  0
    0 2 val =  0
    0 3 val =  0
    0 4 val =  0
    1 0 val =  0
    1 1 val =  0
    1 2 val =  0
    1 3 val =  0
    1 4 val =  0
    2 0 val =  0
    2 1 val =  0
    2 2 val =  0
    2 3 val =  0
    2 4 val =  0 
    

    出于索引目的也值得注意

    for rix in range(nrows):
        for cix in range(ncols):
            print l_of_ls[rix][cix],
        print
    

    结果

    0 0 0 0 0
    0 0 0 0 0
    0 0 0 0 0  
    

    【讨论】:

      【解决方案3】:

      因为真的只有一个列表。考虑一下:

      >>> l = [[]]
      >>> l2 = l*2
      >>> l2[0] is l[0]
      True
      >>> l2[1] is l[0]
      True
      

      在列表上执行*2 不会复制列表,而是返回一个长度为2 的列表,其中填充了相同的引用。

      你可能想要的是这个:

      >>> l = [[] for _ in xrange(2)]
      

      正如@Asterisk 在评论中提到的那样,所有常见的集合都公开了相同的行为。因此,根据经验,最好仅对具有值语义的不可变类型使用乘法

      【讨论】:

      • 似乎 *2 在字典上执行的也没有复制...
      【解决方案4】:

      [[]]*2 是对同一个列表的两个引用的列表。您正在附加它,然后看到它两次。

      【讨论】: