Глава 17 · Архитектура

GameState с dataclass

От прототипных глобальных переменных — к одному типизированному объекту состояния.

GameState — @dataclass (глава 14)

game_state.py
from dataclasses import dataclass, field

@dataclass
class GameState:
    board: list[str] = field(default_factory=lambda: [""] * 9)
    current_player: str = "X"
    game_over: bool = False
    winner: str | None = None
    winning_line: tuple[int, int, int] | None = None
    score_x: int = 0
    score_o: int = 0
    draws: int = 0
НЕ board: list[str] = [""] * 9
Для @dataclass это даже не тихий баг: Python замечает изменяемое значение по умолчанию (list, dict, set) прямо при определении класса и сразу отказывает — ValueError: mutable default <class 'list'> for field board is not allowed: use default_factory. Класс с такой строкой вообще не создастся, значит до «расшаривания между экземплярами» (глава 14 разбирала эту ловушку для обычных изменяемых аргументов по умолчанию) дело не дойдёт. field(default_factory=lambda: [""] * 9) — единственный способ, которым dataclass разрешит дать полю новый список при каждом создании экземпляра.
GameStateboard: list[str]current_player: strgame_over: boolwinner: str | Nonewinning_line: tuple |Nonescore_x: intscore_o: intdraws: int
GameState хранит ТОЛЬКО данные партии — ни одного виджета внутри.
Практика: GameState как dataclass
Автоматическая проверка — умолчания, независимость экземпляров, поля состояния
Открыть практику →