Reputation: 1851
I'm using the Python typing module throughout my project, and I was wondering if there was a way to specify that a given object must be of two different types, at once. This most obviously arises when you have specified two protocols, and expect a single object to fulfil both:
class ReturnsNumbers(Protocol):
def get_number(self) -> Int:
pass
class ReturnsLetters(Protocol):
def get_letter(self) -> str:
pass
def get_number_and_letter(x: <what should this be?>) -> None:
print(x.get_number(), x.get_letter())
Thanks in advance!
Upvotes: 15
Views: 3653
Reputation: 7980
I would say that the other solutions presented have merit except you may have to deal with the case where you have two separate objects that both implement both classes. If you know for sure that the object you want inherits from both ReturnsNumbers
and ReturnsLetters
, you could do this:
T = TypeVar(bound = ReturnsNumbers|ReturnsLetters)
def get_number_and_letter(x: T) -> None:
print(x.get_number(), x.get_letter())
This avoids the explicit definition of a (possibly) useless class while ensuring that you get the type-hinting that you want.
You can find the relevant documentation here.
Upvotes: 4
Reputation: 117771
Create a new type that inherits from all types you wish to combine, as well as Protocol
.
class ReturnsNumbersAndLetters(ReturnsNumbers, ReturnsLetters, Protocol):
pass
def get_number_and_letter(x: ReturnsNumbersAndLetters) -> None:
print(x.get_number(), x.get_letter())
Upvotes: 13
Reputation: 198446
Per this comment on the relevant issue, you can make a simple intersection protocol:
class ReturnsNumbersAndLetters(ReturnsNumbers, ReturnsLetters, Protocol):
pass
then use it instead:
def get_number_and_letter(x: ReturnsNumbersAndLetters) -> None:
print(x.get_number(), x.get_letter())
Upvotes: 6