Python Protocols

In my article Python Type Checking I wrote about type hints. Type hints are around the block since Python 3.5.

Python 3.7 introduced another interesting concept to make Python code even more type safe: Protocols

Duck typing

If it walks like a duck and it quacks like a duck, then it must be a duck

Duck typing is a concept where an object isn’t characterized by its class type but by the presence of methods or attributes. Look at the following code:

class Foo:
    def render(self):
        return "foo"


class Bar:
    def render(self):
        return 2


def render(obj):
    return "I have rendered: " + obj.render()


render(Foo())

render(Bar())

Both classes Foo and Bar have a render method, so when I pass an instance of either class into the global render function the method can be called although Foo and Bar share no common base class.

This is of course a bit dangerous because with duck typing there is no way to determine the return type of a function.

Protocol

Introduced with PEP 544 Protocols are a concept which is also called structural subtyping

Let’s take a closer look:

from typing import Protocol


class Renderable(Protocol):
    def render(self) -> str:
        pass


def render(obj: Renderable) -> str:
    return obj.render()


class Foo:
    def render(self) -> str:
        return "foo"


class Bar:
    def render(self) -> int:
        return 2


render(Foo())
render(Bar())

Before Python 3.7

If You are still working with older Python versions you can install the extension:

pip install typing-extensions
from typing_extensions import Protocol