Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Achieving interface without inheritance in Python

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 ints 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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading