列表操作不正确

时间:2015-05-14 11:57:35

标签: python python-2.7

让我们说

>>> a = [1,2,3,4,5]

我想要一个像

这样的输出
>>> b
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]

这是我的代码:

class Child(object):
    def get_lines(self):
        a = [1,2,3,4,5]              
        b=[]
        c=[]
        j=0
        for i in a:
            print i
            b.append(i)
            print b
            c.insert(j,b)

            j=j+1
        print c


son= Child()
son.get_lines()

当我在循环中打印列表b时,它会给出:

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

,输出为:

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

我在代码中哪里出错?

5 个答案:

答案 0 :(得分:5)

b 始终是相同的列表对象(请注意我已将print c更改为return c):

>>> map(id, Child().get_lines())
...
[49021616, 49021616, 49021616, 49021616, 49021616]

c包含对同一列表的五个引用。我想你想要的是:

class Child(object):

    def get_lines(self):
        a = [1, 2, 3, 4, 5]              
        return [a[:x+1] for x in range(len(a))]

这为每个步骤的部分(或全部)a创建浅拷贝

>>> Child().get_lines()
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]

答案 1 :(得分:2)

替换:

c.insert(j,b)

使用:

 c.append(b[:])

再试一次。

您需要制作b的副本。否则,您会再次添加相同的b,从而在所有索引处生成完整列表。 'b [:]'复制清单。

此解决方案也是如此,但有点短:

a = [1, 2, 3, 4, 5]
c = []
for i in range(1, len(a) + 1):
    c.append(a[:i])

现在c是:

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

a[:i]从头开始对列表a进行切片,以排除索引i。 在这种情况下,它会a[:1]a[:2]等等。 a[:1]制作了一个新列表[1], a[:2]新列表[1, 2,]等等。使用append()更简单,insert()

另一种选择是列表理解:

a = [1, 2, 3, 4, 5]
[a[:i] for i in range(1, len(a) + 1)]

也会导致:

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

答案 2 :(得分:2)

在这种情况下,您不应该将值附加到列表对象(b)。 由于listmutable,因此在重新分配之前,它将引用内存中完全相同的对象。

>>> b=[]
>>> b.append(1)
>>> id(b)
4337935424
>>> b.append(2)
>>> id(b)
4337935424
>>> b.append(3)
>>> id(b)
4337935424
>>> b = [1, 2, 3, 4]
>>> id(b)
4337942608

以便在您的代码中c将对同一列表进行五次引用。

它将指示一个新对象,然后(尽可能)将对它的引用插入到原始对象中。

>>> class Child(object):
...
...     def get_lines(self):
...         a = [1, 2, 3, 4, 5]
...         return map(lambda x: a[:x+1], range(len(a)))
...
>>> Child().get_lines()
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]

答案 3 :(得分:1)

您在列表b中五次插入相同的c。由于列表实际上包含对象而不是副本的引用,因此您有5次引用相同的b列表,其中您已连续添加1,2,3,4,5。因此结果。

您必须添加列表b的副本

def get_lines(self):
    a = [1,2,3,4,5]              
    b=[]
    c=[]
    j=0
    for i in a:
        print i
        b.append(i)
        print b
        c.insert(j,b[:]) # forces insertion of a copy

        j=j+1
    print c

答案 4 :(得分:0)

在循环中,b的值仍然存在,因为它是一个可变对象。因此,当您打印c时,会显示b的最后一个值。

您可以直接使用b,而不是使用a作为临时变量,而不是:

class Child(object):
    def get_lines(self):
        a = [1,2,3,4,5]
        b = []
        for index, element in enumerate(a, 1):
            b.append(x[:index])
        return b


son= Child()
son.get_lines()