Python 间接操作的变量,未在函数中提及

Python variable manipulated indirectly without being mentioned in function

我是一名编码初学者,正在为游戏整合项目。要更新游戏板,我使用这个函数:

Board = [0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
def boardupdate(self, move):
    for index, val in enumerate(move):
        try:
            if val >= 15:
                val -= 3
                move[index] = val
        except TypeError:
            pass
    try: self[move[0]] = 1
    except Exception: None
    try: self[move[1]] = 0
    except Exception: None
    try: self[move[2]] = 0
    except Exception: None
    return self

其中列表的第一项 move 表示棋子在回合中放置的位置,第二项表示棋子从哪里取出(在这个游戏中,您可以放置棋盘上的新棋子或移动棋子),第三项表示棋子从游戏中完全移除的位置。某个回合可能涉及这些动作中的任何一个或 none,因此 tryexcept 块(这是我今天才学到的,所以如果我不正确地使用它们,帮助会很大赞赏)。

该代码在函数内按预期工作,但由于某种原因,在调用此函数后,Board 被更改,就好像它是通过函数 运行 一样。

print(Board)
print(boardupdate(Board, [0, None]))
print(Board)

returns:

[0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

我试图通过将 Board 复制到一个临时变量来解决这个问题,如下所示:

def boardupdate(self, move):
    tempboard = self
    for index, val in enumerate(move):
        try:
            if val >= 15:
                val -= 3
                move[index] = val
        except TypeError:
            pass
    try: tempboard[move[0]] = 1
    except Exception: None
    try: tempboard[move[1]] = 0
    except Exception: None
    try: tempboard[move[2]] = 0
    except Exception: None
    return tempboard

Returns 与之前相同的输出。我怎样才能在不弄乱 Board 的初始条件的情况下更改此函数的输出?这是必要的,以便我的其余代码 运行。谢谢!

tempboard = board 不会复制 board,它只是将 tempboard 绑定到与 board 相同的值。如果你这样做:

tempboard = board.copy()

它实际上会复制board

关于此功能的一些其他杂项建议:

  • 不要调用板参数 self,因为这不是板本身的实例方法。只需将其命名为 board.
  • 不要盲目捕获所有异常;它使错误很难调试。如果您的代码中有错误,您希望它引发异常,这样您就可以立即准确地看到哪里出了问题,而不是花费数小时试图弄清楚它为什么不这样做任何事物!我建议采用一个惯例,即您不进行的移动是 None,然后专门检查 None,而不是忽略任何引发异常的尝试移动。
  • 使用命名变量 and/or 注释来跟踪不同的 move 项目代表什么。
def boardupdate(board, move):
    board = board.copy()
    # Subtract 3 from any move positions >= 15.
    move = [p if p is None or p < 15 else p - 3 for p in move]

    [moved_to, moved_from, removed] = move
    if moved_to is not None:
        board[moved_to] = 1
    if moved_from is not None:
        board[moved_from] = 0
    if removed is not None:
        board[removed] = 0

    return board

您只是指向 Board,并没有实际复制它。在 python 中,出于效率原因,默认情况下不复制可迭代对象。 例如:

x=[1,2,3]
y=x
y[1]=5
print(x)
[1,5,3]

要克服这个问题,您应该在函数内部对 Board 进行深度复制:

tempboard = self.copy()

或者调用函数时:

boardupdate(Board.copy())

这与不可变对象不同,例如整数:

x=5
y=x
y+=1
print(x)
5