Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Вивчайте What typing.Protocol Is and How It Differs | Protocols vs ABCs
Python Abstract Base Classes

What typing.Protocol Is and How It Differs

Свайпніть щоб показати меню

Python 3.8 introduced typing.Protocol as a way to express structural typing – defining an interface based on what methods an object has, without requiring inheritance. Where ABCs use nominal typing ("this class is a subclass of X"), Protocols use structural typing ("this class has the right methods").

Nominal vs Structural Typing

Nominal typing (ABCs): a class must explicitly inherit from or register with the ABC to be considered compatible.

Structural typing (Protocols): a class is compatible if it has the required methods, regardless of its inheritance chain.

12345678910111213141516171819202122232425262728293031
from abc import ABC, abstractmethod from typing import Protocol # Nominal: must inherit from Serializable class Serializable(ABC): @abstractmethod def serialize(self): pass # Structural: any class with serialize() qualifies class SerializableProtocol(Protocol): def serialize(self) -> str: ... # A class that has serialize() but does not inherit from anything class TradeRecord: def serialize(self): return '{"id": "TX-001", "amount": 4500.0}' # ABC – fails without inheritance or register() print(isinstance(TradeRecord(), Serializable)) # False # Protocol – passes because the method exists from typing import runtime_checkable @runtime_checkable class SerializableProtocol(Protocol): def serialize(self) -> str: ... print(isinstance(TradeRecord(), SerializableProtocol)) # True

Defining a Protocol

A Protocol class inherits from typing.Protocol. Methods are defined with ... (ellipsis) as the body – they describe the interface, not an implementation:

123456789101112131415161718192021222324252627282930313233
from typing import Protocol # Protocol defining the interface for a data exporter class Exporter(Protocol): def export(self, data: list) -> str: ... def get_format(self) -> str: ... # Any class with these methods satisfies the protocol class CsvExporter: def export(self, data): return ",".join(str(item) for item in data) def get_format(self): return "CSV" class JsonExporter: def export(self, data): import json return json.dumps(data) def get_format(self): return "JSON" # Both satisfy the protocol without inheriting from it def run_export(exporter: Exporter, data: list) -> None: print(f"Format: {exporter.get_format()}") print(exporter.export(data)) run_export(CsvExporter(), ["TX-001", "TX-002"]) run_export(JsonExporter(), ["TX-001", "TX-002"])

@runtime_checkable

By default, Protocol membership cannot be checked at runtime with isinstance(). Decorating with @runtime_checkable enables it – but the check only verifies method presence, not signatures:

12345678910111213141516
from typing import Protocol, runtime_checkable @runtime_checkable class Runnable(Protocol): def run(self) -> None: ... class BackgroundJob: def run(self): print("Running background job") class BrokenJob: pass print(isinstance(BackgroundJob(), Runnable)) # True – has run() print(isinstance(BrokenJob(), Runnable)) # False – missing run()

ABCs vs Protocols at a Glance

question mark

What is the key difference between nominal typing (ABCs) and structural typing (Protocols)?

Виберіть правильну відповідь

Все було зрозуміло?

Як ми можемо покращити це?

Дякуємо за ваш відгук!

Секція 3. Розділ 1

Запитати АІ

expand

Запитати АІ

ChatGPT

Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат

Секція 3. Розділ 1
some-alt