pythondeque作用域?

pythondeque作用域?,python,list,deque,Python,List,Deque,我正在学习Python,并且一直在尝试制作一个deque。然而,我得到了不正确的输出,我不知道为什么。我的代码如下: 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]

我正在学习Python,并且一直在尝试制作一个deque。然而,我得到了不正确的输出,我不知道为什么。我的代码如下:

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])

您正在将一个对象放入deque中,然后更改该对象。事实上,您总是将同一个对象放入deque中,因此deque中只有一个对象的引用p.

继我对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)
正如我所说,有时它使事情变得更简单,有时不那么简单……但关键是它更容易推理。您不必担心
init_q
中的多个
列表
或者更糟糕的是,这些
列表
中的子
列表
是否共享身份

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

你也可以考虑把它写成一个3D列表,而不是一个2D列表,然后把它输入到<代码> DeQue/COD>。这显然是等效的,但从概念上来说,这样想可能更简单:

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)
另外,如果你正在做很多这类的事情,你可能想看看。如果这是你的全部问题,它不会对你有任何好处……但是如果你对多维数组做任何更复杂的事情,它会的。

我通过简化你的代码创建了一个关于Python的教程。摆弄一下,你就能很容易地看到发生了什么

对代码进行一行更改即可解决此问题

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

下面是使用上述更改的方法。

为了解决这个问题,您可以…?复制对象-
p[:]
,或者如果没有执行,使用
复制
模块对列表进行
深度复制
,然后将副本附加到列表中。谢谢,我不知道我在寻找什么,但我解决了
p[:]
不起作用,但
deepcopy
起作用。所以现在看起来是这样的:
newobj=copy.deepcopy(p)
newobj[i][j]=0
init_q.append(newobj)
如果你被
list
易变性和身份弄糊涂了,另一种解决方法是重写你的代码,使新的
list
就位,而不是修改现有的。(您可以使用
tuple
而不是
list
来验证您没有意外地对任何内容进行变异。)这并不总是让事情变得更简单,但有时确实如此,而且无论哪种方式,都会使推理更容易。您确定预期的输出不是反向的吗?