问题描述
我有一个tictactoe程序,该程序首先创建一个游戏计划,其中每一行都是一个包含空填充符的列表,这意味着正方形为空.
I have a tictactoe program that first creates a gameplan where each row is a list containing an empty filler sign, which means the square is empty.
def createGamePlan(size, sign):
gPlan = []
row = [sign]*size
for i in range(size):
gPlan.append(row)
return gPlan
在用户选择行和列的情况下,我希望更新该特定元素的符号.因此,如果我想将第二行的第一列更新为"X",
With a users choice of row and column I wish to update the sign of that specific element. So if i want to update the 1st column of the 2nd row to an "X" I would have
def updateGamePlan(row, col, gamePlan, sign):
gamePlan[1][0] = "X"
但是,这更改了每一行的第一列,我不知道为什么.我指定其第二行(gamePlan列表的第1个元素,以及内部列表的第0个元素,即第一列).在上面的示例中,有人可以指出出什么问题以及如何解决吗,只能使它更改第二行的第一列,而不是每一行
This however changes the 1st column of every single row and I cant figure out why. I specify that its the 2nd row (1-th element of the gamePlan list, and the 0-th element of that inner list i.e the 1st column). Can someone point out what goes wrong and how I can, in the example above, only make it change the 1st column of the 2nd row, and not every row
推荐答案
要理解的关键是list
对象没有行和列.列表对象是对象的有序异类序列.当您这样做时:
The crucial thing to understand is that list
objects do not have rows and columns. List objects are ordered, heterogeneous sequences of objects. When you do:
def createGamePlan(size, sign):
gPlan = []
row = [sign]*size
for i in range(size):
gPlan.append(row) # appends the SAME object
return gPlan
因此,请考虑以下事项:
So, consider the following:
>>> a = ['foo']
>>> bar = []
>>> for _ in range(4):
... bar.append(a)
...
>>> [id(x) for x in bar]
[4534044744, 4534044744, 4534044744, 4534044744]
对象都是一样的!
>>> bar[0].append('baz')
>>> bar
[['foo', 'baz'], ['foo', 'baz'], ['foo', 'baz'], ['foo', 'baz']]
您创建的列表多次包含同一对象.一个解法?附加副本.
You create a list that contains the same object many times. A solution? Append a copy.
def createGamePlan(size, sign):
gPlan = []
row = [sign]*size
for i in range(size):
gPlan.append(row.copy()) # appends a NEW object
return gPlan
但是请小心,因为.copy
仅复制 shallow .考虑:
Be careful, though, because .copy
only makes a shallow copy. Consider:
>>> row = [['foo'], ['bar']]
>>> grid = []
>>> for _ in range(5):
... grid.append(row.copy())
...
>>> grid
[[['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']]]
好的,膨胀!这些都是独立的对象!:
OK, swell! these are all independant objects!:
>>> [id(x) for x in grid]
[4534044616, 4534135432, 4534135560, 4534135176, 4534135688]
所以...这应该工作正常,不是吗?
So... this should work fine, no?
>>> grid[0][0].append('baz')
>>> grid
[[['foo', 'baz'], ['bar']], [['foo', 'baz'], ['bar']], [['foo', 'baz'], ['bar']], [['foo', 'baz'], ['bar']], [['foo', 'baz'], ['bar']]]
这是怎么回事?好吧,浅表副本创建了新列表,但没有创建新的子列表,即,它没有复制元素中包含的任何元素:
What's going on? Well, a shallow copy created new lists, but not new sublists, i.e., it didn't copy any elements contained in the elements:
>>> [id(x) for row in grid for x in row]
[4534135048, 4534135112, 4534135048, 4534135112, 4534135048, 4534135112, 4534135048, 4534135112, 4534135048, 4534135112]
>>>
为此,您需要一个 deepcopy :
>>> import copy
>>> row = [['foo'], ['bar']]
>>> grid = []
>>> for _ in range(5):
... grid.append(copy.deepcopy(row))
...
>>> grid
[[['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']]]
>>> [id(x) for row in grid for x in row]
[4534135432, 4534135368, 4534135176, 4534135880, 4534136328, 4534161928, 4534135112, 4534162120, 4534162248, 4534162184]
>>> grid[0][0].append('baz')
>>> grid
[[['foo', 'baz'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']], [['foo'], ['bar']]]
>>>
这篇关于更改列表中列表的第n个元素会更改列表中所有列表的第n个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!