Python подсказки типа для соответствия другому классу, с общим поведением - PullRequest
0 голосов
/ 15 января 2020

Привет всем. Я ищу лучший способ напечатать подсказку для своей функции, где я хочу принимать разные типы классов, но с общим поведением. пример:

class HumanPlayer:
    pass

class IAPlayer:
    pass

def play_game(player1, player2)
    pass

Как добавить подсказки типа для player1 и player2, которые могут поддерживать оба типа игроков? Конечно, я могу использовать object или создать родительский класс Player. Но я уверен, что это не то решение.

Ответы [ 2 ]

2 голосов
/ 15 января 2020

Прямой ответ будет состоять в использовании typing.Union и намека на:

Union[HumanPlayer, IAPlayer]

Однако это означает, что переданный объект может иметь любые признаки либо класс. Пока оба класса реализуют один и тот же интерфейс, это не имеет значения. Но трудно держать оба класса в syn c просто по соглашению, поэтому вам следует подумать о формальном способе помочь этому процессу, используя общий родительский класс. ABC очень полезен в этом отношении:

from abc import ABC, abstractmethod

class Player(ABC):
    def something_common(self):
        # do something common

    @abstractmethod
    def play(self):
        """Players must implement their specific play style."""
        raise NotImplementedError

    ...

class HumanPlayer(Player):
    def play(self):
        # play humanely

    def care_for_bodily_needs(self):
        # take a break

Теперь вы можете смело намекать на Player и его четко определенный интерфейс. Если HumanPlayer или IAPlayer реализуют что-то, чего нет у другого, это не будет включено в интерфейс Player и, следовательно, не может безопасно использоваться внутри вашей функции play_game, делая ваш тип кода безопасным.

def play_game(player1: Player, player2: Player):
    player1.something_common()
    player1.play()
    player2.play()

def ensure_is_comfortable(player: HumanPlayer):
    player.care_for_bodily_needs()  # only safe to call here
1 голос
/ 15 января 2020

Одним из решений было бы добавить общего предка для обоих классов и использовать его в качестве подсказки типа:

class PlayerMixin:
    pass

class HumanPlayer(PlayerMixin):
    pass

class AIPlayer(PlayerMixin):
    pass

def play_game(player1: PlayerMixin, player2: PlayerMixin)
    pass
...