49

运行代码

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), ...
4

7 回答 7

52

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

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().

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

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

于 2012-07-14T20:19:27.670 回答
25

我来到这里是因为我是 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)]]

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

于 2014-09-29T23:55:48.803 回答
13

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

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

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

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

您可以使用构造函数创建整个列表的副本:alist

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

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

listoflists.append((a[:], a[0]))
于 2012-07-14T20:18:55.403 回答
3

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

在线上

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

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

使用复制库

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

使用切片符号

listoflists.append((list[:], list[0]))
于 2012-07-14T20:26:09.400 回答
3

当你运行代码

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

您没有(正如我认为您所期望的那样)listlistoflists. 您正在做的是添加listlistoflists. 因此,每次更新时list,它都会更新对 的每个引用list,在这种情况下,就是listoflists

你可以做的是这样的:

listoflists = []
for i in range(1, 10):
    listoflists.append((range(i), 0))
于 2012-07-14T20:20:02.960 回答
2

只要您仅在 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)
于 2012-07-14T20:21:42.873 回答
2

时间旅行者在这里

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 从零开始,但是 range(x-2,x+1) 从 -2 开始,这不是我们想要的,所以如果 z >= 0 的条件语句放在 ( 2)

[z for z in range(x-2,x+1) if z >= 0] 
于 2018-07-30T06:58:37.593 回答