我正在制作国际象棋,玩AI并且有一个minimax算法,当前在选择移动后返回游戏状态:board,white_pieces和black_pieces。
我的国际象棋类处理移动国家的生成和维护。它有一些全局变量:
__board
__white_pieces
__black_pieces
在类中声明:body但在任何方法之外。这应该使它成为一个全局变量。
在游戏开始时,这些是使用build_board方法初始化的(并不总是为了测试代码而实现)。我想现在可以将它移动到 init ()方法,因为我已经测试了代码。
def build_board(self):
for i in range(1, 17):
self.__board[self.__white_pieces[i][1]] = i
self.__white_pieces[i][3] = True
self.__board[self.__black_pieces[i][1]] = -1 * i
self.__black_pieces[i][3] = True
for i in range(0, 20):
self.__board[i] = 99
for i in range(100, 120):
self.__board[i] = 99
for i in range(0, 8):
self.__board[20 + 10 * i] = 99
self.__board[20 + 10 * i + 9] = 99
我认为这是有道理的,因为它使用的是一个可变类型的列表。好没问题。这编辑了董事会。
然后,当我尝试让游戏处理minimax返回的游戏状态并更新这些全局变量时,这些都不会更新它:
def play_move(self,board,white_pieces,black_pieces):
global __board
global __white_pieces
global __black_pieces
__board = board
__white_pieces = white_pieces
__black_pieces = black_pieces
或
def play_move(self,board,white_pieces,black_pieces):
self.__board = board
self.__white_pieces = white_pieces
self.__black_pieces = black_pieces
我是否误解了全局变量如何在一个类中起作用?如果有人能为我清除这一点,那就太好了。谢谢!
编辑: 我甚至可以让playmove方法返回self .__ board,self .__ white_pieces,self .__ black_pieces tuple并打印出来,如果它们实际上是更新的动作,它们是。在该方法中,并将这些结果传递给另一个方法,声明self .__ xxxxx已更新。但是,从该方法的外部来看,它似乎不会更新全局变量。
答案 0 :(得分:0)
变量宣告"在课堂内:身体但在任何方法之外"成为类属性,而不是全局变量。类属性在类的所有实例之间共享,因此可能不是您想要的。
请注意,除非有相同名称的实例属性遮蔽它,否则您可以从实例访问类属性(并将其变更),但只要您设置(在实例上这个属性,它将创建一个将影响类属性的实例属性:
>>> class Foo(object):
... bar = []
... def add(self, x):
... self.bar.append(x)
... def set(self, bar):
... self.bar = bar
...
>>> f1 = Foo()
>>> f1.bar
[]
>>> id(f1.bar)
140281150134752
>>> f2 = Foo()
>>> f2.bar
[]
>>> id(f2.bar)
140281150134752
>>> f2.bar is f1.bar
True
>>> f1.add(42)
>>> f2.bar
[42]
>>> f1.bar
[42]
>>> f1.set([33])
>>> f1.bar
[33]
>>> f2.bar
[42]
>>> f2.bar is Foo.bar
True
>>> f1.bar is Foo.bar
False
>>>
鉴于你的用例和代码片段,我认为你真的希望你的board
等是实例属性而不是全局或类属性。
你提到:
每种方法都需要能够访问电路板的当前状态并进行修改。
但这恰好是拥有实例属性的要点:对象的所有方法都共享对象的状态(=>属性)。
作为旁注,除非你真的知道它的作用并且真的需要它,否则不要在你的属性前加上双下划线(提示:你可能或许这需要每10年左右一次......)。单个前导下划线是表示它是实现细节的惯例,而不是类API的一部分。