我正在学习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])
答案 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
。如果这是你的整个问题,它对你没有任何帮助......但是如果你做任何更复杂的多维数组,它会。