Модификация для list.copy () применяется к списку - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь смоделировать шахматную игру в python 3 с объектно-ориентированным программированием. Один из классов, который я использую, это Board, который содержит матрицу (список 8x8) с другим объектом. Я также создал простой метод __str__ для визуализации шахматной доски.

Вот некоторая часть определения класса Совета:

class Board:
    def __init__(self, pieces: list):
        self.container = [[pieces[i] for i in range(8)],  # Whites
                          [pieces[i] for i in range(8, 16)],  # White pawns
                          [None] * 8,
                          [None] * 8,
                          [None] * 8,
                          [None] * 8,
                          [pieces[i] for i in range(16, 24)],  # Black pawns
                          [pieces[i] for i in range(24, 32)]]  # Blacks


    def __str__(self):
        str_copy = self.container.copy()

        for i in range(8):
            for j in range(8):
                if isinstance(str_copy[i][j], King):
                    str_copy[i][j] = 'K'
                elif isinstance(str_copy[i][j], Queen):
                    str_copy[i][j] = 'Q'
                elif isinstance(str_copy[i][j], Rook):
                    str_copy[i][j] = 'R'
                elif isinstance(str_copy[i][j], Knight):
                    str_copy[i][j] = 'N'
                elif isinstance(str_copy[i][j], Bishop):
                    str_copy[i][j] = 'B'
                elif isinstance(str_copy[i][j], Pawn):
                    str_copy[i][j] = 'P'
                elif str_copy[i][j] is None:
                    str_copy[i][j] = '_'

        return ''.join([str(line) + '\n' for line in str_copy])

Моя проблема в том, что в какой-то момент в моем коде Board.container кажется перезаписанным str_copy. Я действительно не могу понять, почему. Вот полный код, если вы хотите взглянуть на него: pastebin

Большое спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 13 апреля 2020

Я немного поторопился, закрывая вопрос. Учитывая текущую ошибку, это действительно дублирование из [SO]: как клонировать или скопировать список? .
Но при ближайшем рассмотрении это действительно проблема XY . Простое дублирование этого объекта только для демонстрации, не только уродливо, но и ненужно. Вот более элегантная альтернатива:

Добавить новый (класс) метод к Piece (чтобы избежать изменения поведения __ str __ или __ repr __ , я назвал это буква ):

@classmethod
def letter(cls):
    raise NotImplementedError

и переопределение его во всех его дочерних элементах ( Король , Королева , Ладья, Рыцарь , Епископ , Пешка ). Например, в случае King это должно быть:

@classmethod
def letter(cls):
    return "K"

Я думаю, довольно очевидно, как это будет выглядеть для остальных.

Тогда, Board .__ str __ может быть что-то вроде:

def __str__(self):
    return "\n".join("".join(getattr(piece, "letter", lambda: "_")() for piece in line) for line in self.container)
0 голосов
/ 13 апреля 2020

Это слишком сложно. Во-первых, каждый кусок должен иметь свой собственный метод __str__, например,

class Bishop:
    ...

    def __str__(self):
        return 'B'

Затем

class Board:
    def __init__(self, pieces: list):
        self.container = [pieces[:8],  # white back row
                          pieces[8:16],  # white pawns
                          [None] * 8,
                          [None] * 8,
                          [None] * 8,
                          [None] * 8,
                          pieces[16:24],  # black pawns
                          pieces[24:32]   # black back row
                         ]

    @staticmethod
    def _square_to_str(x):
        return '_' if x is None else str(x)

    def __str__(self):
        return '\n'.join(''.join(map(Board._square_to_str, row))
                          for row in self.container)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...