实例变量自动修改
Instance variable gets modified automatically
我制作了一个新的 class,代表 Tic Tac Toe 游戏中的一个位置。基本上我想做的是制作一棵游戏位置所有可能性的树,其中每个节点都是一个 Position
对象,并使用 minimax 算法为玩家找到最佳移动。由于位置 class 未按要求工作,minimax 算法未在下方显示。
Position
class 有一个 generate_children
方法,它生成一个列表 Position
可以从当前位置到达的对象。执行程序我们得到输出,在每次迭代后,当前 Position
对象的 pos_matrix
正在改变,这是不希望的。我没有触及循环中当前 Position 对象的 pos_matrix
并且 play_move
复制矩阵以避免弄乱它。 pos_matrix
仍然在每次迭代中发生变化。
这是怎么回事?如何调试?
已尝试:将 play_move
从 class 中移出,但没有用。
注意:pos_matrix中的0
表示空方块,1
表示"X"和-1
代表"O".
另外 kiska_chance
表示 "whose chance"。 :P
class Position:
def __init__(self, parent_):
self.parent = parent_
self.children = []
self.best_move = []
self.pos_matrix = []
self.last_move = []
def set_pos_matrix(self, pos_matrix_):
self.pos_matrix = list(pos_matrix_)
# Avoiding copying problems by creating copy of list
def set_last_move(self, last_move_):
self.last_move = list(last_move_)
# Avoiding copying problems by creating copy of list
def play_move(self, move, kiska_chance):
m2 = list(self.pos_matrix)
x, y = move
m2[x][y] = kiska_chance
return m2
def generate_children(self, kiska_chance):
children_ = []
for move in self.get_possible_moves():
# Passing a Position object into the possible moves with
# parent as self.
pos_temp = Position(self)
pos_temp.set_pos_matrix(self.play_move(move, kiska_chance))
pos_temp.set_last_move(move)
print self.pos_matrix
children_.append(pos_temp)
self.children = children_
return children_
def get_possible_moves(self):
dem_moves = []
for i in xrange(3):
for j in xrange(3):
if self.pos_matrix[i][j]==0:
dem_moves.append([i, j])
return dem_moves
pos = Position(None)
pos.set_pos_matrix([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
pos.generate_children(1)
您在 self.pos_matrix
中有嵌套列表。您只是在复制外部列表。因此,列表中的所有列表仍由两个列表共享。您需要复制列表中的列表。查看更正后的代码:
def play_move(self, move, kiska_chance):
m2 = list(list(l) for l in self.pos_matrix)
x, y = move
m2[x][y] = kiska_chance
return m2
也在:
def set_pos_matrix(self, pos_matrix_):
self.pos_matrix = list(list(l) for l in pos_matrix_)
# Avoiding copying problems by creating copy of list and lists in list
通常你必须为此使用 deepcopy
,因为 lists
是 mutable
对象,它们将通过引用传递给其他对象。
让我们看看同时具有 mutable
和 immutable
个对象的列表会发生什么。
>>> l1 = [1, 2]
>>> l2 = [3, 4]
>>> t1 = (1, 2, 3)
>>> l = [l1, l2, t1, 5]
>>> l
[[1, 2], [3, 4], (1, 2, 3), 5]
这里 list l
有 l1 and l2
,然后是 tuple t1
,然后是一个数字 5
,所以 list
是一个 mutable
对象,并且number 和 tuples
不是。
如果你简单地做一个 list(l)
变成了 shallow copy
,浅拷贝意味着只复制最外面的对象,但你的内部对象仍然引用相同的对象。
为此你最好使用 copy
模块。
import copy
>>> l_copy = copy.copy(l)
现在我们在这里做了一个 shallow copy
..让我们看看会发生什么。
>>> l_copy
[[1, 2], [3, 4], (1, 2, 3), 5]
我们得到了与 l
相同的列表,让我们尝试将一个值附加到 inner list
。
>>> l_copy[0]
[1, 2]
>>> l_copy[0].append(0)
>>> l_copy
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
现在 l[0] --> [1, 2] 又增加了一个值 [1,2, 0]..如果你尝试检查 l
和 l1
你可以在那里也看到相同的值。
>>> l
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
>>> l1
[1, 2, 0]
您没有修改 l and l1
,但它们仍然获得了新的价值 0
如果您的 mutable
个对象会发生这种情况。
让我们在这里尝试 deepcopy
.. 注意:您必须再次定义 l1, l2 and l
不要使用旧的..
>>> l_copy = copy.deepcopy(l)
>>> l_copy
[[1, 2], [3, 4], (1, 2, 3), 5]
现在将值附加到 l_copy[0]
这意味着附加到 l1
..
>>> l_copy[0].append(0)
>>> l_copy
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
并尝试使用 l1 and l
..
检查
>>> l
[[1, 2], [3, 4], (1, 2, 3), 5]
>>> l1
[1, 2]
如果您现在看到该值 not
反映了 l1 and l
。
所以你必须小心 mutable
对象。并且可以参考下面的文档以获取有关 copy
和 deepcopy
.
的更多信息
我制作了一个新的 class,代表 Tic Tac Toe 游戏中的一个位置。基本上我想做的是制作一棵游戏位置所有可能性的树,其中每个节点都是一个 Position
对象,并使用 minimax 算法为玩家找到最佳移动。由于位置 class 未按要求工作,minimax 算法未在下方显示。
Position
class 有一个 generate_children
方法,它生成一个列表 Position
可以从当前位置到达的对象。执行程序我们得到输出,在每次迭代后,当前 Position
对象的 pos_matrix
正在改变,这是不希望的。我没有触及循环中当前 Position 对象的 pos_matrix
并且 play_move
复制矩阵以避免弄乱它。 pos_matrix
仍然在每次迭代中发生变化。
这是怎么回事?如何调试?
已尝试:将 play_move
从 class 中移出,但没有用。
注意:pos_matrix中的0
表示空方块,1
表示"X"和-1
代表"O".
另外 kiska_chance
表示 "whose chance"。 :P
class Position:
def __init__(self, parent_):
self.parent = parent_
self.children = []
self.best_move = []
self.pos_matrix = []
self.last_move = []
def set_pos_matrix(self, pos_matrix_):
self.pos_matrix = list(pos_matrix_)
# Avoiding copying problems by creating copy of list
def set_last_move(self, last_move_):
self.last_move = list(last_move_)
# Avoiding copying problems by creating copy of list
def play_move(self, move, kiska_chance):
m2 = list(self.pos_matrix)
x, y = move
m2[x][y] = kiska_chance
return m2
def generate_children(self, kiska_chance):
children_ = []
for move in self.get_possible_moves():
# Passing a Position object into the possible moves with
# parent as self.
pos_temp = Position(self)
pos_temp.set_pos_matrix(self.play_move(move, kiska_chance))
pos_temp.set_last_move(move)
print self.pos_matrix
children_.append(pos_temp)
self.children = children_
return children_
def get_possible_moves(self):
dem_moves = []
for i in xrange(3):
for j in xrange(3):
if self.pos_matrix[i][j]==0:
dem_moves.append([i, j])
return dem_moves
pos = Position(None)
pos.set_pos_matrix([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
pos.generate_children(1)
您在 self.pos_matrix
中有嵌套列表。您只是在复制外部列表。因此,列表中的所有列表仍由两个列表共享。您需要复制列表中的列表。查看更正后的代码:
def play_move(self, move, kiska_chance):
m2 = list(list(l) for l in self.pos_matrix)
x, y = move
m2[x][y] = kiska_chance
return m2
也在:
def set_pos_matrix(self, pos_matrix_):
self.pos_matrix = list(list(l) for l in pos_matrix_)
# Avoiding copying problems by creating copy of list and lists in list
通常你必须为此使用 deepcopy
,因为 lists
是 mutable
对象,它们将通过引用传递给其他对象。
让我们看看同时具有 mutable
和 immutable
个对象的列表会发生什么。
>>> l1 = [1, 2]
>>> l2 = [3, 4]
>>> t1 = (1, 2, 3)
>>> l = [l1, l2, t1, 5]
>>> l
[[1, 2], [3, 4], (1, 2, 3), 5]
这里 list l
有 l1 and l2
,然后是 tuple t1
,然后是一个数字 5
,所以 list
是一个 mutable
对象,并且number 和 tuples
不是。
如果你简单地做一个 list(l)
变成了 shallow copy
,浅拷贝意味着只复制最外面的对象,但你的内部对象仍然引用相同的对象。
为此你最好使用 copy
模块。
import copy
>>> l_copy = copy.copy(l)
现在我们在这里做了一个 shallow copy
..让我们看看会发生什么。
>>> l_copy
[[1, 2], [3, 4], (1, 2, 3), 5]
我们得到了与 l
相同的列表,让我们尝试将一个值附加到 inner list
。
>>> l_copy[0]
[1, 2]
>>> l_copy[0].append(0)
>>> l_copy
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
现在 l[0] --> [1, 2] 又增加了一个值 [1,2, 0]..如果你尝试检查 l
和 l1
你可以在那里也看到相同的值。
>>> l
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
>>> l1
[1, 2, 0]
您没有修改 l and l1
,但它们仍然获得了新的价值 0
如果您的 mutable
个对象会发生这种情况。
让我们在这里尝试 deepcopy
.. 注意:您必须再次定义 l1, l2 and l
不要使用旧的..
>>> l_copy = copy.deepcopy(l)
>>> l_copy
[[1, 2], [3, 4], (1, 2, 3), 5]
现在将值附加到 l_copy[0]
这意味着附加到 l1
..
>>> l_copy[0].append(0)
>>> l_copy
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
并尝试使用 l1 and l
..
>>> l
[[1, 2], [3, 4], (1, 2, 3), 5]
>>> l1
[1, 2]
如果您现在看到该值 not
反映了 l1 and l
。
所以你必须小心 mutable
对象。并且可以参考下面的文档以获取有关 copy
和 deepcopy
.