> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Protocol

A `Protocol` in Python is a base class provided by the `typing` module that enables structural subtyping (often referred to as static duck typing). Introduced in PEP 544, it allows developers to define an interface based on the presence of specific methods and attributes, rather than requiring explicit inheritance (nominal subtyping). If a class implements the members defined in a `Protocol` with matching type signatures, static type checkers recognize it as a subtype of that `Protocol`.

## Syntax and Definition

A Protocol is defined by inheriting from `typing.Protocol`. The interface shape is established using type hints and the `...` (Ellipsis) literal for method bodies, indicating that the implementation is deferred to the structural subtype.

```python theme={"dark"}
from typing import Protocol

class DataHandler(Protocol):
    # Defines a required attribute
    buffer_size: int 

    # Defines a required method signature
    def process(self, payload: bytes) -> bool:
        ...
```

## Structural vs. Nominal Subtyping

Python traditionally relies on nominal subtyping via Abstract Base Classes (`abc.ABC`). In nominal subtyping, a class must explicitly declare its relationship to the interface. `Protocol` bypasses this requirement.

```python theme={"dark"}

# Implicitly satisfies DataHandler without inheriting from it
class StreamProcessor:
    def __init__(self) -> None:
        self.buffer_size = 1024

    def process(self, payload: bytes) -> bool:
        return len(payload) < self.buffer_size


# Static type checkers evaluate this as valid:
def execute_handler(handler: DataHandler) -> None:
    handler.process(b"data")

execute_handler(StreamProcessor()) # Valid structural subtype
```

## Runtime Behavior and Introspection

By default, Protocols exist purely for static type analysis (e.g., via `mypy` or `pyright`). They are erased at runtime. Attempting to use `isinstance()` or `issubclass()` against a standard `Protocol` will raise a `TypeError`.

To enable runtime introspection, the `Protocol` must be decorated with `typing.runtime_checkable`.

```python theme={"dark"}
from typing import Protocol, runtime_checkable

@runtime_checkable
class Serializable(Protocol):
    def serialize(self) -> str:
        ...

class User:
    def serialize(self) -> str:
        return "UserObject"


# Valid at runtime due to @runtime_checkable
is_serializable = isinstance(User(), Serializable)  # Evaluates to True
```

**Technical Caveat:** `@runtime_checkable` only verifies the *presence* of the required attributes and methods. Because Python does not enforce type hints at runtime, it cannot verify that the method signatures or attribute types of the instance actually match the Protocol's definition.

## Generic Protocols

Protocols can be combined with `TypeVar` to create generic structural interfaces. The `Protocol` class inherently supports the mechanics of `typing.Generic`.

```python theme={"dark"}
from typing import Protocol, TypeVar

T = TypeVar('T')

class Container(Protocol[T]):
    def add(self, item: T) -> None:
        ...
    
    def get(self) -> T:
        ...
```

## Callable Protocols

While `typing.Callable` is sufficient for simple function signatures, Protocols can define complex callable signatures by implementing the `__call__` dunder method. This is necessary when a function type requires overloaded signatures, keyword-only arguments, or generic type variables that depend on each other.

```python theme={"dark"}
from typing import Protocol

class ComplexCallback(Protocol):
    def __call__(self, data: str, *, strict: bool = False) -> int:
        ...
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Python Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
