How do I define and use Protocols in typing?

Understanding and using Protocols in Python's typing module allows for more flexible and dynamic type checking, enabling the design of more robust interfaces.
Python, typing, Protocols, type checking, dynamic typing, interfaces

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None:
        ...

class Circle:
    def draw(self) -> None:
        print("Drawing a Circle")

class Square:
    def draw(self) -> None:
        print("Drawing a Square")

def render(shape: Drawable) -> None:
    shape.draw()

circle = Circle()
square = Square()

render(circle)  # Output: Drawing a Circle
render(square)  # Output: Drawing a Square
    

Python typing Protocols type checking dynamic typing interfaces