【问题标题】:Python 3.5 list comprehension modifies original [duplicate]Python 3.5列表理解修改了原始[重复]
【发布时间】:2015-12-21 21:20:35
【问题描述】:

我老了,没有头发可以拔了。我已经阅读了尽可能多的类似问题的答案,因为我可以在 SO 上找到。我有以下代码:

a = [[1,2],[3,4],[4,5]]
b = ['a','b','c']
print('a:',a)
print('b:',b)
c = a[:]
print('c == a:', c==a)
print('c is a:',c is a)
print('id(c) = id(a):', id(c)==id(a))
[x.extend(b) for x in c]
print('c after:',c)
print('a after:',a)`

输出是:

a: [[1, 2], [3, 4], [4, 5]]
b: ['a', 'b', 'c']
c == a: True
c is a: False
id(c) = id(a): False
c after: [[1, 2, 'a', 'b', 'c'], [3, 4, 'a', 'b', 'c'], [4, 5, 'a', 'b', 'c']]
a after: [[1, 2, 'a', 'b', 'c'], [3, 4, 'a', 'b', 'c'], [4, 5, 'a', 'b', 'c']]

我正在寻找显示为“c after:”的结果,但我不明白为什么 a 也被修改了?! 我也试过了

c = list(a)

c = copy.copy(a)

当然,简单的 c = a 不能按预期工作。 我错过了什么?! 谢谢。

【问题讨论】:

    标签: python list object reference list-comprehension


    【解决方案1】:

    这是因为您没有复制列表中的元素。 a 内的列表不会被复制。因此,您的 extend 方法会影响两个列表中的元素。您应该使用c = copy.deepcopy(a) 来复制嵌套元素。

    【讨论】:

      【解决方案2】:

      尝试像这样分配 c 列表,(没有 .copy() 解决方案)

      c = []
      for elem in a:
          c.append(list(elem))
      

      或一个带有列表理解的班轮

      c = [list(elem) for elem in a]
      

      如果列表中有列表,这将提供深层复制,当然不是 3 层。

      您所做失败的原因是您设法正确复制了列表,但里面的列表仍然引用相同的内存值,因此元素列表中没有副本。此解决方案还复制内部列表,这是 deepcopy 的定义。

      【讨论】:

        【解决方案3】:

        正如其他发帖人所解释的,A 中的列表实际上并未复制到 C - 它们只是对原始列表的引用。运行下面的代码可以看到:

        num_lists = [[1,2],[3,4],[4,5]]
        lists_copy = num_lists[:]
        
        orig_first = num_lists[0]
        copy_first = lists_copy[0]
        
        print('Are the first elements the same object?', orig_first is copy_first)
        

        打印“True”,表示lists_copy 中的[1,2] 实际上是num_lists 中的[1,2]。复制 Python 列表太复杂了,我希望他们将来能把它改得更友好。到目前为止,您能做的最好的事情是: lists_copy = copy.deepcopy(num_lists)

        您可以在下面看到它的工作原理:

        from copy import deepcopy
        
        lists_copy = deepcopy(num_lists)
        
        orig_first = num_lists[0]
        copy_first = lists_copy[0]
        
        print('Are they they the same after copying with deepcopy?', orig_first is copy_first)
        

        这段代码打印“False”,表示列表被安全复制,余额最终恢复到宇宙中:)

        【讨论】:

          【解决方案4】:

          还要考虑到列表是可变类型,与不可变类型(例如字符串)相比,可以在创建后对其进行修改。不可变类型在创建后无法更改。因此,如果您尝试向其附加第二个字符串,则会生成一个字符串的真实副本。可变类型可以更改。因此,没有复制,并且 a 和 c 都引用了同一个列表。

          【讨论】:

            猜你喜欢
            • 2019-03-27
            • 2014-02-03
            • 1970-01-01
            • 1970-01-01
            • 2016-10-26
            • 2017-06-05
            • 2012-12-18
            • 2015-03-10
            • 2011-06-15
            相关资源
            最近更新 更多