Reputation: 4855
Hello everyone I'm looking for the best way to type hinting my function where I want to accept different types of class, but with common behavior. example:
class HumanPlayer:
pass
class IAPlayer:
pass
def play_game(player1, player2)
pass
How can I add type hints for player1
and player2
that can support the both kinds of players?
Of course I can use object
or create a parent class Player
. But I'm sure that this are not the right solucion.
Upvotes: 0
Views: 115
Reputation: 522165
The straight forward answer would be to use typing.Union
and hint against:
Union[HumanPlayer, IAPlayer]
However, this means that the passed object may have any traits of either class. As long as both classes implement the same interface, that doesn't really matter. But it's hard to keep both classes in sync just by convention, so you should think about a formal way to help that process by using a shared parent class. An ABC
is very useful in this regard:
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
Now you can safely hint against Player
and its well defined interface. If HumanPlayer
or IAPlayer
implement something the other doesn't, that won't be included in the Player
interface and thus cannot safely be used inside your function play_game
, making your code type safe.
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
Upvotes: 2
Reputation: 9359
One solution would be to add a common ancestor for both classes, and use it as the type hint:
class PlayerMixin:
pass
class HumanPlayer(PlayerMixin):
pass
class AIPlayer(PlayerMixin):
pass
def play_game(player1: PlayerMixin, player2: PlayerMixin)
pass
Upvotes: 1