【问题标题】:Python: list of listsPython:列表列表
【发布时间】:2012-07-14 06:45:58
【问题描述】:

运行代码

listoflists = []
list = []
for i in range(0,10):
    list.append(i)
    if len(list)>3:
        list.remove(list[0])
        listoflists.append((list, list[0]))
print listoflists

返回

[([7, 8, 9], 0), ([7, 8, 9], 0), ([7, 8, 9], 0), ([7, 8, 9], 1), ([7, 8, 9], 2), ([7, 8, 9], 3), ([7, 8, 9], 4), ([7, 8, 9], 5), ([7, 8, 9], 6), ([7, 8, 9], 7)]

所以不知何故,每个元组(列表)的第一个参数每次都在列表列表中更新,但第二个参数 list[0] 不是。有人可以解释这里发生了什么并提出解决此问题的方法吗?我要输出

[([0],0), ([0,1],0), ...

【问题讨论】:

标签: python


【解决方案1】:

首先,我强烈建议您将变量 list 重命名为其他名称。 list 是内置列表构造函数的名称,您隐藏了它的正常功能。下面我将list重命名为a

Python 名称是绑定到对象的引用。这意味着除非您创建多个列表,否则每当您使用a 时,它指的是与上次相同的实际列表对象。所以当你打电话时

listoflists.append((a, a[0]))

您可以稍后更改a,它会更改该元组的第一个元素指向的内容。 a[0] 不会发生这种情况,因为a[0] 指向的对象(整数)不会改变(尽管a[0] 在代码运行过程中指向不同的对象)。

您可以使用list 构造函数创建整个列表a副本

listoflists.append((list(a), a[0]))

或者,您可以使用 slice 表示法 进行复制:

listoflists.append((a[:], a[0]))

【讨论】:

    【解决方案2】:

    列表是一种可变类型 - 为了创建一个副本(而不是仅仅传递相同的列表),您需要明确地这样做:

    listoflists.append((list[:], list[0]))
    

    但是,list 已经是 Python 内置的名称 - 最好不要为变量使用该名称。这是一个不使用list作为变量名的版本,并进行了复制:

    listoflists = []
    a_list = []
    for i in range(0,10):
        a_list.append(i)
        if len(a_list)>3:
            a_list.remove(a_list[0])
            listoflists.append((list(a_list), a_list[0]))
    print listoflists
    

    请注意,我演示了复制上述列表的两种不同方法:[:]list()

    第一个,[:],正在创建一个 slice(通常用于获取列表的一部分),它恰好包含整个列表,因此实际上是列表。

    第二个,list(),使用实际的list类型构造函数创建一个新列表,其内容等于第一个列表。 (我没有在第一个示例中使用它,因为您在代码中覆盖了该名称 - 这是您不想这样做的一个很好的示例!)

    【讨论】:

    • len(listoflists) 将返回 listoflists 中有多少个列表。
    【解决方案3】:

    当你运行代码时

    listoflists.append((list, list[0]))
    

    您不会(正如我想的那样)将list 的副本添加到listoflists 的末尾。您正在做的是将list 的引用添加到listoflists 的末尾。因此,每次更新 list 时,它都会更新对 list 的每个引用,在这种情况下,它是 listoflists 中的每个项目

    你可以做的是这样的:

    listoflists = []
    for i in range(1, 10):
        listoflists.append((range(i), 0))
    

    【讨论】:

      【解决方案4】:

      只要你只在 if 子句内附加到 listoflists,你也不会得到你希望的输出。

      试试这样的:

      import copy
      
      listoflists = []
      list = []
      for i in range(0,10):
          list.append(i)
          if len(list)>3:
              list.remove(list[0])
          listoflists.append((copy.copy(list), copy.copy(list[0])))
      print(listoflists)
      

      【讨论】:

        【解决方案5】:

        list 变量(我建议将其重命名为更合理的名称)是对列表对象的引用,可以更改。

        上线

        listoflists.append((list, list[0]))
        

        您实际上只是通过列表变量添加对对象引用的引用。您有多种可能性来创建列表的副本,因此 listoflists 包含您似乎期望的值:

        使用复制库

        import copy
        listoflists.append((copy.copy(list), list[0]))
        

        使用切片符号

        listoflists.append((list[:], list[0]))
        

        【讨论】:

          【解决方案6】:

          我来到这里是因为我是 python 新手并且很懒,所以我正在搜索一个示例来创建一个包含 2 个列表的列表,过了一会儿意识到这里的主题可能是错误的...... 这是创建列表列表的代码:

          listoflists = []
          for i in range(0,2):
              sublist = []
              for j in range(0,10)
                  sublist.append((i,j))
              listoflists.append(sublist)
          print listoflists
          

          这是输出 [ [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), ( 0, 8), (0, 9)], [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), ( 1, 8), (1, 9)] ]

          您的代码的问题似乎是您正在使用列表创建一个元组,并且您获得了对列表的引用而不是副本。我猜应该属于元组主题...

          【讨论】:

          • 这不会给出 OP 要求的输出。
          • 对,但我认为这比问题本身更符合问题的标题,通常人们登陆这里是因为他们只想创建一个列表列表,而不是因为他们在更新元组列表时遇到问题...可能是因为我将此站点用作学习工具而不是调试工具:-)
          【解决方案7】:

          这里是时间旅行者

          List_of_list =[([z for z in range(x-2,x+1) if z >= 0],y) for y in range(10) for x in range(10)]
          

          这应该可以解决问题。输出是这样的:

          [([0], 0), ([0, 1], 0), ([0, 1, 2], 0), ([1, 2, 3], 0), ([2, 3, 4], 0),  ([3, 4, 5], 0), ([4, 5, 6], 0), ([5, 6, 7], 0), ([6, 7, 8], 0), ([7, 8, 9], 0), ([0], 1), ([0, 1], 1), ([0, 1, 2], 1), ([1, 2, 3], 1), ([2, 3, 4], 1), ([3, 4, 5], 1), ([4, 5, 6], 1), ([5, 6, 7], 1), ([6, 7, 8], 1), ([7, 8, 9], 1), ([0], 2), ([0, 1], 2), ([0, 1, 2], 2), ([1, 2, 3], 2), ([2, 3, 4], 2), ([3, 4, 5], 2), ([4, 5, 6], 2), ([5, 6, 7], 2), ([6, 7, 8], 2), ([7, 8, 9], 2), ([0], 3), ([0, 1], 3), ([0, 1, 2], 3), ([1, 2, 3], 3), ([2, 3, 4], 3), ([3, 4, 5], 3), ([4, 5, 6], 3), ([5, 6, 7], 3), ([6, 7, 8], 3), ([7, 8, 9], 3), ([0], 4), ([0, 1], 4), ([0, 1, 2], 4), ([1, 2, 3], 4), ([2, 3, 4], 4), ([3, 4, 5], 4), ([4, 5, 6], 4), ([5, 6, 7], 4), ([6, 7, 8], 4), ([7, 8, 9], 4), ([0], 5), ([0, 1], 5), ([0, 1, 2], 5), ([1, 2, 3], 5), ([2, 3, 4], 5), ([3, 4, 5], 5), ([4, 5, 6], 5), ([5, 6, 7], 5), ([6, 7, 8], 5), ([7, 8, 9], 5), ([0], 6), ([0, 1], 6), ([0, 1, 2], 6), ([1, 2, 3], 6), ([2, 3, 4], 6), ([3, 4, 5], 6), ([4, 5, 6], 6), ([5, 6, 7], 6), ([6, 7, 8], 6), ([7, 8, 9], 6), ([0], 7), ([0, 1], 7), ([0, 1, 2], 7), ([1, 2, 3], 7), ([2, 3, 4], 7), ([3, 4, 5], 7), ([4, 5, 6], 7), ([5, 6, 7], 7), ([6, 7, 8], 7), ([7, 8, 9], 7), ([0], 8), ([0, 1], 8), ([0, 1, 2], 8), ([1, 2, 3], 8), ([2, 3, 4], 8), ([3, 4, 5], 8), ([4, 5, 6], 8), ([5, 6, 7], 8), ([6, 7, 8], 8), ([7, 8, 9], 8), ([0], 9), ([0, 1], 9), ([0, 1, 2], 9), ([1, 2, 3], 9), ([2, 3, 4], 9), ([3, 4, 5], 9), ([4, 5, 6], 9), ([5, 6, 7], 9), ([6, 7, 8], 9), ([7, 8, 9], 9)]    
          

          这是通过列表理解完成的(这使得通过一行代码循环列表中的元素成为可能)。这段代码背后的逻辑如下:

          (1) for x in range(10) 和 for y in range(10) 用于列表内的两个独立循环

          (2)(a list, y)是循环的总称,这也是为什么在(1)中放在两个for之前的原因

          (3)(2)中列表的长度不能超过3,并且列表依赖于x,所以

          [z for z in range(x-2,x+1)] 
          

          被使用

          (4) 因为 z 从 0 开始,但是 range(x-2,x+1) 从 -2 开始,这不是我们想要的,所以如果 z >= 0 的条件语句放在末尾在(2)中列出

          [z for z in range(x-2,x+1) if z >= 0] 
          

          【讨论】:

            猜你喜欢
            • 2022-06-16
            • 2021-04-01
            • 2020-02-20
            • 1970-01-01
            • 2020-08-06
            • 1970-01-01
            • 1970-01-01
            • 2011-04-21
            • 2011-08-19
            相关资源
            最近更新 更多