不通过类方法

时间:2017-07-20 15:01:33

标签: python class global-variables updates

我正在制作国际象棋,玩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已更新。但是,从该方法的外部来看,它似乎不会更新全局变量。

1 个答案:

答案 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的一部分。