Python deque范围?

时间:2013-01-07 03:27:06

标签: python list deque

我正在学习Python并且一直试图制作一个双端队列。但是,我输出不正确,我不知道为什么。我的代码如下:

p = [2, 1], [1, 1]
init_q= deque()

init_q.append(p)
for i in range(len(p)):
    for j in range(len(p[i])):
        temp = p[i][j]
        p[i][j] = 0
        init_q.append(p)
        p[i][j] = temp

while init_q:
    print init_q.pop()

在这段代码中,我接受一个列表,然后我想创建一个包含5个列表的队列,其中4个在不同的位置有一个0,我想要的结果是:

([2, 1], [1, 1])
([0, 1], [1, 1])
([2, 0], [1, 1])
([2, 1], [0, 1])
([2, 1], [1, 0])

然而,我得到的结果是:

([2, 1], [1, 1])
([2, 1], [1, 1])
([2, 1], [1, 1])
([2, 1], [1, 1])
([2, 1], [1, 1])

3 个答案:

答案 0 :(得分:4)

您正在将一个对象放入双端队列中,然后更改对象。实际上,你总是将相同的对象放入双端队列中,因此所有的双端队列都是对一个对象的引用。

答案 1 :(得分:3)

我通过简化代码在Python Tutor上创建了visualization。摆弄,你可以很容易地看到发生了什么。

对代码进行单行更改可以解决此问题。

init_q.append(map(list, p))    # Initialize a new list from p's element lists

通过使用上述更改,这是visualization

答案 2 :(得分:1)

继续对Ned Batchelder的回答发表评论,以下是你如何能够以不可改变的方式做同样的事情:

for i in range(len(p)):
    for j in range(len(p[i])):
        temprow = [0 if y==j else p[i][y] for y in range(len(p[i]))]
        temp = [temprow if x==i else p[x] for x in range(len(p))]
        init_q.append(temp)

在这种情况下,我认为结果的可读性远低于他的建议:

        temp = copy.deepcopy(p)
        temp[i][j] = 0
        init_q.append(temp)

正如我所说,有时它会使事情变得更简单,有时也会变得简单......但关键是它更容易推理。您不必担心list中的多个init_q - 或者更糟糕的是,list内的list个是{@ 1}}是否正在共享身份。

权衡是否值得,实际上是个案决策,对每个程序员来说可能都不同。在这种情况下,我不会使用不可变的解决方案,我怀疑许多其他(Python)程序员会。但值得知道如何写它。

您也可以考虑将其写为3D列表,而不是2D列表的双端队列,然后将其输入deque。它显然是等价的,但从概念上讲,这样思考可能更简单:

init_q.append(p)
q = [copy.deepcopy(p) for i in range(len(p)) for j in range(len(p[i]))]
for i in range(len(p)):
    for j in range(len(p[i])):
        q[i*len(p[i])+j][i][j] = 0
init_q.extend(q)
PS,如果你做了很多这类事情,你可能想看看numpy。如果这是你的整个问题,它对你没有任何帮助......但是如果你做任何更复杂的多维数组,它会。