为什么这个变量会改变?

Why is this variable changing?

我正在和我的朋友一起编写一个国际象棋界面来取乐,最终我们都制作了机器人并与他们一决高下。当我重新评估寻找支票的合法动作时,我遇到了障碍,因为它们应该是非法动作。界面的实际代码有几千行,但我简化了代码以显示问题。我将 post 可以复制问题的简化代码,然后是我认为导致问题的关键部分。 简化代码:

class Pieces():

    def __init__(self):

        self.white_pawns_inf = [[0, 1, False, True], [1, 1, False, True], [2, 1, False, True], [3, 1, False, True], [4, 1, False, True], [5, 1, False, True], [6, 1, False, True], [7, 1, False, True]]
        self.white_bishops_inf = [[2, 0, False], [5, 0, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False]]
        self.white_knights_inf = [[1, 0, False], [6, 0, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False]]
        self.white_rooks_inf = [[0, 0, False, True], [7, 0, False, True], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False]]
        self.white_queens_inf = [[3, 0, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False]]
        self.white_king_inf = [[4, 0, True, True]]

        self.black_pawns_inf = [[0, 6, True, True], [1, 6, True, True], [2, 6, True, True], [3, 6, True, True], [4, 6, True, True], [5, 6, True, True], [6, 6, True, True], [7, 6, True, True]]
        self.black_bishops_inf = [[2, 2, True], [5, 7, True], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False]]
        self.black_knights_inf = [[6, 2, True], [6, 7, True], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False]]
        self.black_rooks_inf = [[0, 7, True, True], [7, 7, True, True], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False], [0, 7, False, False]]
        self.black_queens_inf = [[3, 7, True], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False], [0, 7, False]]
        self.black_king_inf = [[4, 7, True, True]]

        self.white_occupation_x = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7]
        self.white_occupation_y = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]

        self.black_occupation_x = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7]
        self.black_occupation_y = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]

    def check_checks(self):

        take = True

        for notation_val in ['a6', 'a5', 'b6', 'b5', 'c6', 'c5', 'd6', 'd5', 'e6', 'e5', 'f6', 'f5', 'g6', 'g5', 'h6', 'h5']:

            #print(self.black_pawns_inf)
            black_pawns = self.black_pawns_inf
            #print(self.black_pawns_inf)

            if True:

                if True:
                        
                    tox = notation.get_column_char(notation_val[-2])
                    toy = int(notation_val[-1]) - 1

                    if True:

                        fromx = tox

                        if True:

                            if toy == 4:

                                fromy = toy + 2

                                for i in range(0, 8):

                                    if black_pawns[i][2] == True and black_pawns[i][0] == fromx and black_pawns[i][1] == toy + 1:

                                        fromy = toy + 1

                            else:

                                fromy = toy + 1

                    if True:

                        for i in range(0, 8):

                            if black_pawns[i][2] == True and black_pawns[i][0] == fromx and black_pawns[i][1] == fromy:

                                print(self.black_pawns_inf)
                                
                                black_pawns[i][0] = tox
                                black_pawns[i][1] = toy
                                black_pawns[i][3] = False
                                
                                print(self.black_pawns_inf)
                                
class Notation():

    def __init__(self):

        pass
    
    def get_column(self, x):
        
        if x == 0:

            return "a"

        elif x == 1:

            return "b"

        elif x == 2:

            return "c"

        elif x == 3:

            return "d"

        elif x == 4:

            return "e"

        elif x == 5:

            return "f"

        elif x == 6:

            return "g"

        elif x == 7:

            return "h"

    def get_column_char(self, x):
        
        if x == "a":

            return 0

        elif x == "b":

            return 1

        elif x == "c":

            return 2

        elif x == "d":

            return 3

        elif x == "e":

            return 4

        elif x == "f":

            return 5

        elif x == "g":

            return 6

        elif x == "h":

            return 7

    def get_row(self, y):

        for i in range(0, 8):

            if y == i:

                return str(i + 1)

        if y != 0 and y != 1 and y != 2 and y != 3 and y != 4 and y != 5 and y != 6 and y != 7:

            return "9"

white_turn = False
        
pieces = Pieces()
notation = Notation()
#print(pieces.black_pawns_inf)
pieces.check_checks()
#print(pieces.black_pawns_inf)

关键部分是:

print(self.black_pawns_inf)

black_pawns[i][0] = tox
black_pawns[i][1] = toy
black_pawns[i][3] = False

print(self.black_pawns_inf)

black_pawns = self.black_pawns_inf

问题是,变量“self.black_pawns_inf”在函数中发生了变化,它出现一次(不包括打印语句),其中设置了 black_pawns。这个变量改变对我来说毫无意义。如上所示,变量更改的隔离代码区域位于第一个关键部分。我在之前和之后打印变量,它发生了变化,即使据称改变它的 3 行代码甚至不包括这个变量!!!我假设我在 python 中遗漏了一些东西,它在相互设置的变量之间创建了一个 link 并且以某种方式通过改变一个,它也改变了另一个。下面我将显示当程序为 运行 for notation_val in ['a6', 'a5', 'b6', [=29] 的第一次迭代时的输出=], 'c6', 'c5', 'd6', 'd5', 'e6', 'e5', 'f6', 'f5' , 'g6', 'g5', 'h6', 'h5']:" 其中变化发生:

[[0, 6, True, True], [1, 6, True, True], [2, 6, True, True], [3, 6, True, True], [4, 6, True, True], [5, 6, True, True], [6, 6, True, True], [7, 6, True, True]]
[[0, 5, True, False], [1, 6, True, True], [2, 6, True, True], [3, 6, True, True], [4, 6, True, True], [5, 6, True, True], [6, 6, True, True], [7, 6, True, True]]

如您所见,每个列表中的第一个列表发生变化 - 6 变为 5,True 变为 False - 这对于变量“black_pawns”是预期的,但对于变量“[=42”也会发生=]"...

我已尽力解释问题,如有任何帮助,我们将不胜感激,谢谢!

I assume I am missing something in python that it creates a link between variables that are set to each other and somehow by changing one, it also changes the other.

你是对的 - Python 中的某些类型(例如 list 可变的 并且会显示此行为。 ints 和 strs 等其他类型是 immutable 并且没有这种行为。请参阅有关此主题的 previous answer 以获取解释。

您可以复制 self.black_pawns_inf 以避免就地修改。在您的情况下,您有一个列表列表,因此您需要进行深拷贝以避免就地修改它:

from copy import deepcopy

black_pawns = deepcopy(self.black_pawns_inf)

然后您将能够修改 black_pawns 的元素,而无需修改 self.black_pawns_inf 的元素。