Protocols and duck typing
Python does not ask what class an object is. It asks whether the object has the attribute you are about to use. That is duck typing: if it has .read(), it can be read.
def shout(thing):
return thing.text().upper()Any object with a text method works, and no shared base class is needed.
Writing the contract down
typing.Protocol names the shape you expect, so type checkers can verify it. Classes do not inherit from it.
from typing import Protocol
from typing import runtime_checkable
@runtime_checkable
class HasText(Protocol):
def text(self) -> str: ...
class Note:
def text(self):
return "hi"
isinstance(Note(), HasText) # Trueruntime_checkable allows isinstance, but it only checks that the method name exists. It does not look at parameters or return types.
Your task
Write a runtime-checkable protocol Renderer with render(self) -> str. Write classes Text(value) rendering the value and Bold(value) rendering **value**, neither inheriting from Renderer. Write render_all(items) joining the rendered items with newlines.
The explanation opens here once every check passes.