【问题标题】:I would expect the output to be like [[0,0,0,0,],[0,1,0,0],[0,2,0,0],[0,3,0,0]]我希望输出类似于 [[0,0,0,0,],[0,1,0,0],[0,2,0,0],[0,3,0,0]]
【发布时间】:2019-01-15 09:16:23
【问题描述】:
time_count = [[0, 0, 0, 0]] * 4
j = 0
for i in range(len(time_count)):
    time_count[i][1] = j
    j += 1
print(time_count)

输出:

[[0, 3, 0, 0], [0, 3, 0, 0], [0, 3, 0, 0], [0, 3, 0, 0]]

我希望输出是这样的:

[[0,0,0,0],[0,1,0,0],[0,2,0,0],[0,3,0,0]] 

有人能解释一下为什么每个index[1] 都是3 吗?

【问题讨论】:

  • * 运算符创建对(相同)列表的新引用。如果你改变一个,你就改变了所有。
  • 太棒了!我明白了,但是如何在不写下每个元素的情况下创建一个长列表?

标签: python list loops nested-lists assign


【解决方案1】:

基本上,列表的实体是指向特定内存位置的指针。当将 list(a) 分配给 list(b) 时,这意味着 list(b) 指向与 list(a) 相同的内存位置。

 a = [1, 2, 3]
 b = a
 a = [3, 4, 5]
 print(a, b)

 [3, 4, 5] [1, 2, 3]

在上述问题中,如果嵌套列表的内部乘以 4 倍,则所有子列表都指向同一个内存位置。因此,如果其中一个子列表发生更改,则更改将传播到所有子列表,这基本上会在代码执行时产生意外结果。对于任何有兴趣了解更多信息的人, 该视频总结了列表中不明显的所有基本特征。它还更详细地解释了上述问题。 https://www.youtube.com/watch?v=_AEJHKGk9ns

【讨论】:

    【解决方案2】:

    列表不宜写成[[0, 0, 0, 0]]*4。列表是可变的。每次更改任何列表元素时,它的所有副本都会更改。一种好的编写方法如下,因为这样您就不会复制列表元素。

    [[0, 0, 0, 0] for i in range(4)]
    

    【讨论】:

      【解决方案3】:

      做:

      time_count = [[0, 0, 0, 0]] * 4
      print([[v if x!=1 else i for x,v in enumerate(a)] for i,a in enumerate(time_count)])
      

      输出:

      [[0, 0, 0, 0], [0, 1, 0, 0], [0, 2, 0, 0], [0, 3, 0, 0]]
      

      更新:

      说明:

      1. 使用enumerate 遍历列表time_count 的索引和值。

      2. 再次使用enumerate 遍历列表a 的索引和值。 这是time_count的迭代器

      3. 如果xa 的索引迭代器)为 1,则遍历a 的索引并说itime_count 的索引迭代器),否则说va 的迭代器)

      注意:这一切都在列表理解中

      【讨论】:

      • 兄弟!你能用简单的英语分解上面的打印语句吗?究竟是什么意思??
      • @bitbitbitter 编辑了我的答案
      【解决方案4】:

      * 运算符只是创建对原始列表的新引用(此处为 [0, 0, 0, 0])。

      如果您将原始列表更改为time_count[i][1] = j,则所有引用都会反映相同的更改。

      如果你想创建一个新列表,你可以使用带有循环的extend方法:

      time_count = []
      time_count.extend([0,0,0,0] for _ in range(4))
      

      现在,time_count 中的所有元素列表都存储单独的内存并且可以有不同的值。

      【讨论】:

        【解决方案5】:

        简单修复:

        time_count = [[0, 0, 0, 0] for _ in range(4)]
        

        正如 Klaus D. 所暗示的,在嵌套列表上使用 * 运算符通常是一个坏主意,因为它通过复制引用来复制内容。当乘以不可变类型的序列时,您不会注意到这一点,例如整数列表,但当元素可变时,您会得到重复。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-08
          • 2022-01-14
          • 2023-01-05
          • 2019-05-25
          相关资源
          最近更新 更多