{
    "slug": "py_protocol",
    "term": "Structural Subtyping with Protocol",
    "category": "python",
    "difficulty": "intermediate",
    "short": "Protocol classes define structural interfaces — any class with matching methods satisfies the protocol without explicit inheritance (type-safe duck typing).",
    "long": "Protocol (typing.Protocol, Python 3.8+): a class satisfies a Protocol if it has all required attributes and methods, regardless of inheritance. Unlike ABC (which requires explicit subclassing), Protocol works at type-check time without modifying existing classes. @runtime_checkable enables isinstance() checks at runtime. Use for: typing third-party classes you cannot modify, documenting expected interfaces without coupling to a class hierarchy, and expressing duck types with static type safety.",
    "aliases": [
        "Protocol",
        "structural subtyping",
        "duck typing Python",
        "typing.Protocol",
        "runtime_checkable"
    ],
    "tags": [
        "python",
        "types",
        "oop"
    ],
    "misconception": "Protocol requires explicit registration like ABC — Protocol uses structural subtyping; any class with matching methods satisfies it at type-check time with no changes to the implementing class.",
    "why_it_matters": "Without Protocol, a function accepting any object with a read() method must use Any (loses type safety) or a custom ABC (requires modifying all implementing classes). Protocol gives type safety without coupling.",
    "common_mistakes": [
        "Using Protocol when ABC is more appropriate — use ABC when you want enforcement at class definition time",
        "Not adding @runtime_checkable when isinstance() checks are needed",
        "Protocol with mutable attributes — structural subtyping with mutable attributes can be surprising",
        "Forgetting that satisfying the Protocol is checked at type-check time not runtime (without @runtime_checkable)"
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "py_walrus_operator",
        "py_dataclasses_advanced",
        "typescript_interfaces_types"
    ],
    "prerequisites": [
        "py_type_hints",
        "interfaces",
        "duck_typing"
    ],
    "refs": [
        "https://peps.python.org/pep-0544/"
    ],
    "bad_code": "# Any type — loses all type safety:\ndef process(reader: Any) -> str:\n    return reader.read()  # No type checking — any attribute access allowed\n\n# ABC — requires modifying existing classes:\nfrom abc import ABC, abstractmethod\nclass Readable(ABC):\n    @abstractmethod\n    def read(self) -> str: ...\n# All implementing classes must inherit Readable — invasive coupling",
    "good_code": "from typing import Protocol, runtime_checkable\n\n@runtime_checkable\nclass Readable(Protocol):\n    def read(self) -> str: ...\n\ndef process(reader: Readable) -> str:\n    return reader.read()  # Type-checked — must have read() -> str\n\n# Any class with read() -> str satisfies it — no inheritance needed:\nclass FileReader:\n    def read(self) -> str: return open(self.path).read()\n\nclass MockReader:\n    def read(self) -> str: return 'mock data'\n\nprocess(FileReader())  # Type-safe\nprocess(MockReader())  # Type-safe\nisinstance(MockReader(), Readable)  # True (runtime_checkable)",
    "quick_fix": "Use Protocol to define structural interfaces in Python — any class with the required methods satisfies the Protocol without explicit inheritance, enabling PHP-style interface checking with Python's duck typing",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-03-16",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/py_protocol",
        "html_url": "https://codeclaritylab.com/glossary/py_protocol",
        "json_url": "https://codeclaritylab.com/glossary/py_protocol.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Structural Subtyping with Protocol](https://codeclaritylab.com/glossary/py_protocol) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/py_protocol"
            }
        }
    }
}