Python
Protocol
Learn structural typing with typing.Protocol.
What is Protocol for?
Protocol provides structural typing. Even without inheriting from a Protocol, a class is considered conforming if it has the right methods. It is imported from the typing module.
Example: class Drawable(Protocol):\n def draw(self) -> str: .... Any class that provides draw is considered a Drawable; it does not need to inherit. With @runtime_checkable you can also enable isinstance checks.
@runtime_checkable
To check a protocol with isinstance you use the @runtime_checkable decorator. It decides conformance by looking only at method signatures on the protocol.
Example: @runtime_checkable\nclass Speaker(Protocol):\n def speak(self) -> str: .... The call isinstance(obj, Speaker) returns True if obj has a speak method. This is the most practical way to check conformance without an inheritance relationship.
Exercise Drawable protocol and Circle
Start with from typing import Protocol, runtime_checkable. Define @runtime_checkable and class Drawable(Protocol):; inside, write def draw(self) -> str: .... Then define class Circle: (no inheritance); in the body write def draw(self) -> str: and return "circle". Finally create c = Circle() and print conformance with print(isinstance(c, Drawable)).
Show example solution
# Write the Drawable protocol and the Circle class
from typing import Protocol, runtime_checkable
@runtime_checkable
class Drawable(Protocol):
def draw(self) -> str: ...
class Circle:
def draw(self) -> str:
return "circle"
c = Circle()
print(isinstance(c, Drawable))
Test yourself
-
Match the Protocol parts
- Protocol
- Base class
- typing
- Module
- @runtime_checkable
- isinstance permission
- def draw(self)
- Expected method
-
What is needed to conform to a Protocol?
- Having the right methods
- Filling abstract methods
- Inheriting ABC
- Inheritance
Show answer
Having the right methods — Protocol accepts having the right methods; no inheritance required.
-
Protocol import line
from typing import Protocol, ____
@runtime_checkable
class Drawable(Protocol):
def draw(self) -> str: ...
Show answer
from typing import Protocol, runtime_checkable
@runtime_checkable
class Drawable(Protocol):
def draw(self) -> str: ...
Next lesson: Interface vs abstract