TIL: python Protocol and typing
Hi there,
I’m still learning a lot around Python, and I discovered Protocol some months ago and I wanted to write that down to not forget.
Protocol was created in Python 3.8 with the PEP 544. There a multiple protocols in python but the one I’m talking about is a way to define structural typing. Some of you will also call that implicit interface. We can use the Protocol class from the typing module. To not confuse you even more, I will explain that with a simple image.
If we consider you as a journalist and you are writing tech articles, week notes and many type of writing; you always have things you will do for your posts despite the type of them, for example, such as:
- mark it as draft
- publish
To make sure you not forget those things, let’s create a template, so you don’t forget them. This template will be your protocol.
With real code it should look like something like this:
from typing import Protocol class Publishable(Protocol): def publish(self): pass
That’s it, you can use it on any types of posts you want without inheritating them. This means that an object conforms to a protocol by implementing the required methods. Here’s an example with the publish method:
class Article: def __init__(self, title: str): self.title = title def publish(self) -> None: # do something to publish pass
The class Article is now implementing the protocol Publishable with the addition of the required method publish.
The pro and cons of that are:
Pro
- No need of inheritance pattern, less direct links and avoid drawbacks of inheritance if you make changes
- Don’t forget to implement things and have more dynamics
Cons
- Less readable, you have to know that
- Useful mostly for typing
I guess right now you’re thinking, great but how do I use this Protocol? Good question!
Protocols are primarily used for type hinting and static type checking. This means you can use a protocol as a type annotation to indicate that an argument or variable must conform to a specific protocol.
If we retake our example, we will have this following code:
def publish_article(article: Article) -> None: article.publish() ...
In this case it’s only one Protocol used, but you could have multiple Protocols used.
class Draft(Protocol): def mark_as_draft(self): # do something to mark as draft pass class DraftAndPublishable(Draft, Publishable): pass
In this example, we define a protocol named Draft with a mark_as_draft method. Then we define another protocol named DraftAndPublishable that combines both the Draft and Publishable protocols.
If you are familiar with the special methods __iter__ and __next__, if you implement both, then your object will use the Iterator protocol ✨ You can learn more on Real Python blog post related to Iterator Protocol.
To conclude with, Protocols provide a way to define structural typing in Python, allowing you to create interfaces without the need for explicit inheritance. They enable type checkers to verify that objects adhere to the defined protocols, enhancing code correctness and maintainability.
That’s it for now! I hope it will be useful for someone.