I have a sorted linked list
class SortedLinkedList:
# ...
def insert(self, value: int):
# ...
if node.value > value:
self.add_before(node, value)
# ...
I would like to generalize the type of values that a Node
can hold from only int
s to any object that overloads the >
operator by implementing the __gt__()
magic method.
In other languages I would achieve this by using an Interface
, but Python apparently has no analog. I've seen suggestions to fake interfaces by using abstract classes like
class Sortable(ABC):
@abstractmethod
def __gt__(self, other) -> bool:
pass
class SortedLinkedList:
# ...
def insert(self, value: Sortable, node: Node):
# ...
The problem is this approach requires extending and using subclasses from Sortable
, which means types that already have >
functionality like integers cannot be used
linkedlist.insert(5) # Pylance red squiggles
Argument of type "Literal[5]" cannot be assigned to
parameter "value" of type "Sortable" in function "insert"
"Literal[5]" is incompatible with "Sortable" Pylance(reportGeneralTypeIssues)
I understand that Interfaces are not necessary pre-runtime given Python's dynamic duck typing and implicit style. I am not a fan, and am opting to use available tooling like typing and Pylance to achieve a strictly typed developer experience.
I am also not looking to use runtime checks like .hasattr(value, '__gt__')
. I'm wanting this to register on the type system/language server/IDE level, as expressivity, readability, and IDE intellisense are the main benefits of strict typing.
Is there any way to achieve this?
CodePudding user response:
What you're looking for is typing.Protocol
.
class Sortable(Protocol):
def __gt__(self, other) -> bool: ...
With this, any class that defines __gt__
will be detected as an implicit subtype of Sortable
.