I prefer ABCs beacuse they're explicit. With a Protocol someone reading the code may not know your class is intended to implement an interface in another module or deep in a dependency. Similarly, you can accidentally conform to a Protocol's signature, without conforming to its contract. For example, if a function accepts a
class Image(Protocol):
def draw() -> None:
...
it's obviously not going to make sense with a
class Cowboy:
def draw() -> None:
...
but the type checker would happily accept it.
Answer from joel on Stack OverflowVideos
Hi everyone. Last time I shared a post about Interface programming using abs in Python, and it got a lot of positive feedback—thank you!
Several people mentioned protocols, so I wrote a new article exploring that topic. In it, I compare protocols with abstract base classes and share my thoughts and experiences with both. You can check it out here: https://www.tk1s.com/python/protocols-vs-abstract-base-classes-in-python Hope you'll like it! Thanks!
Hello, if one finds interfaces useful in Python (>=3.8) and is convinced that static type-checking is a must, then why not ditch ABC and always use Protocols? I understand that the fundamental idea of a protocol is slightly different from an interface, but in practice, I had great success replacing abc's with Protocols without regrets.
With abc you would write (https://docs.python.org/3/library/abc.html) :
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def eat(self, food) -> float:
passWhereas with Protocols it's gonna be (good tutorial):
from typing import Protocol
class Animal(Protocol):
def eat(self, food) -> float:
...Scores in my subjective scoring system :)
| Capability | ABC | Protocols |
|---|---|---|
| Runtime checking | 1 | 1 (with a decorator) |
| Static checking with mypy | 1 | 1 |
Explicit interface (class Dog(Animal):) | 1 | 1 |
Implicit interface with duck-typing (class Dog:) | 0.5 (kind of with register, but it doesn't work with mypy yet) | 1 |
Default method implementation (def f(self): return 5) | -1 (implementations shouldn't be in the interfaces) | -1 (same, and mypy doesn't catch this) |
| Callback interface | 0 | 1 |
| Number of code lines | -1 (requires ABC inheritance and abstracmethod for every method) | 0 (optionalProtocol inheritance) |
| Total score | 1.5 | 4 |
So I do not quite see why one should ever use ABC except for legacy reasons. Other (IMHO minor) points in favour of ABC I've seen were about interactions with code editors.
Did I miss anything?
I put more detailed arguments into a Medium. There are many tutorials on using Protocols, but not many on ABC vs Protocols comparisons. I found a battle of Protocols vs Zope, but we are not using Zope, so it's not so relevant.