New in Python 3.8:

Some of the benefits of interfaces and protocols are type hinting during the development process using tools built into IDEs and static type analysis for detection of errors before runtime. This way, a static analysis tool can tell you when you check your code if you're trying to access any members that are not defined on an object, instead of only finding out at runtime.

The typing.Protocol class was added to Python 3.8 as a mechanism for "structural subtyping." The power behind this is that it can be used as an implicit base class. That is, any class that has members that match the Protocol's defined members is considered to be a subclass of it for purposes of static type analysis.

The basic example given in PEP 544 shows how this can be used.

Copyfrom typing import Protocol

class SupportsClose(Protocol):
    def close(self) -> None:
        # ...

class Resource:
    # ...
    def close(self) -> None:
        self.file.close()
        self.lock.release()

def close_all(things: Iterable[SupportsClose]) -> None:
    for thing in things:
        thing.close()

file = open('foo.txt')
resource = Resource()
close_all([file, resource])  # OK!
close_all([1])     # Error: 'int' has no 'close' method

Note: The typing-extensions package backports typing.Protocol for Python 3.5+.

Answer from gooberwonder on Stack Overflow
🌐
Python
peps.python.org › pep-0544
PEP 544 – Protocols: Structural subtyping (static duck typing) | peps.python.org
March 5, 2017 - This includes treating all the builtin protocols, such as Iterable structurally. The runtime implementation of protocols is available in typing_extensions module on PyPI. ... This document has been placed in the public domain. Source: https://github.com/python/peps/blob/main/peps/pep-0544.rst
🌐
GitHub
github.com › python › mypy › issues › 10482
Inconsistent Treatment of Class Constructor by Protocol · Issue #10482 · python/mypy
May 16, 2021 - In effect we're describing a "factory". However, while MyPy is able to recognize incorrect protocol implementations when given a function, it fails to do the same for class constructors. Playground link: https://mypy-play.net/?mypy=latest&python=3.9&gist=3b9250b17032b659fc36746e659bcdb5 ·
Published   May 16, 2021
Author   rmorshea
🌐
GitHub
github.com › protocolbuffers › protocolbuffers.github.io › blob › main › content › reference › python › python-generated.md
protocolbuffers.github.io/content/reference/python/python-generated.md at main · protocolbuffers/protocolbuffers.github.io
The protocol buffer compiler also generates a "stub" implementation of every service interface, which is used by clients wishing to send requests to servers implementing the service. For the Foo service (above), the stub implementation Foo_Stub will be defined. Foo_Stub is a subclass of Foo. Its constructor takes an RpcChannel as a parameter.
Author   protocolbuffers
🌐
GitHub
github.com › python › mypy › issues › 12970
Protocol can't constrain __init__ · Issue #12970 · python/mypy
June 11, 2022 - from typing import Protocol, Type class Proto(Protocol): def __init__(self, x: int) -> None: ... class Impl: def __init__(self) -> None: ...
Author   glyph
🌐
GitHub
github.com › modelcontextprotocol › python-sdk
GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients · GitHub
This Python SDK implements the full MCP specification, making it easy to: Build MCP clients that can connect to any MCP server · Create MCP servers that expose resources, prompts and tools · Use standard transports like stdio, SSE, and Streamable HTTP · Handle all MCP protocol messages and lifecycle events
Starred by 22.3K users
Forked by 3.2K users
Languages   Python
Top answer
1 of 8
65

New in Python 3.8:

Some of the benefits of interfaces and protocols are type hinting during the development process using tools built into IDEs and static type analysis for detection of errors before runtime. This way, a static analysis tool can tell you when you check your code if you're trying to access any members that are not defined on an object, instead of only finding out at runtime.

The typing.Protocol class was added to Python 3.8 as a mechanism for "structural subtyping." The power behind this is that it can be used as an implicit base class. That is, any class that has members that match the Protocol's defined members is considered to be a subclass of it for purposes of static type analysis.

The basic example given in PEP 544 shows how this can be used.

Copyfrom typing import Protocol

class SupportsClose(Protocol):
    def close(self) -> None:
        # ...

class Resource:
    # ...
    def close(self) -> None:
        self.file.close()
        self.lock.release()

def close_all(things: Iterable[SupportsClose]) -> None:
    for thing in things:
        thing.close()

file = open('foo.txt')
resource = Resource()
close_all([file, resource])  # OK!
close_all([1])     # Error: 'int' has no 'close' method

Note: The typing-extensions package backports typing.Protocol for Python 3.5+.

2 of 8
21

In short, you probably don't need to worry about it at all. Since Python uses duck typing - see also the Wikipedia article for a broader definition - if an object has the right methods, it will simply work, otherwise exceptions will be raised.

You could possibly have a Piece base class with some methods throwing NotImplementedError to indicate they need to be re-implemented:

Copyclass Piece(object):

    def move(<args>):
        raise NotImplementedError(optional_error_message) 

class Queen(Piece):

    def move(<args>):
        # Specific implementation for the Queen's movements

# Calling Queen().move(<args>) will work as intended but 

class Knight(Piece):
    pass

# Knight().move() will raise a NotImplementedError

Alternatively, you could explicitly validate an object you receive to make sure it has all the right methods, or that it is a subclass of Piece by using isinstance or isubclass. Note that checking the type may not be considered "Pythonic" by some and using the NotImplementedError approach or the abc module - as mentioned in this very good answer - could be preferable.

Your factory just has to produce instances of objects having the right methods on them.

🌐
Mypy
mypy.readthedocs.io › en › stable › protocols.html
Protocols and structural subtyping - mypy 1.19.1 documentation
In Python 3.9 and later, the aliases in typing don’t provide any extra functionality. You can define your own protocol class by inheriting the special Protocol class:
🌐
Andrewbrookins
andrewbrookins.com › technology › building-implicit-interfaces-in-python-with-protocol-classes
Building Implicit Interfaces in Python with Protocol Classes – Andrew Brookins
July 5, 2020 - So, why is this called a “protocol” and what kinds of things is it good for? Let’s go deeper to answer those questions. The built-in function len() works with any object that has a __len__() method. Objects don’t have to declare that they have a __len__() method or subclass any special classes to work with len(). Python programmers call this state of affairs a protocol, and the most common example is probably the iteration protocol.
Find elsewhere
🌐
Python
typing.python.org › en › latest › spec › protocol.html
Protocols — typing documentation
If a class defines all attributes and methods of a protocol with types that are assignable to the types of the protocol’s attributes and methods, it is said to implement the protocol and to be assignable to the protocol. If a class is assignable to a protocol but the protocol is not included in the MRO, the class is implicitly assignable to the protocol.
🌐
GitHub
github.com › autoprotocol › autoprotocol-python
GitHub - autoprotocol/autoprotocol-python: Python library for generating Autoprotocol
import json from autoprotocol.protocol import Protocol # instantiate a protocol object p = Protocol() # generate a ref # specify where it comes from and how it should be handled when the Protocol is done plate = p.ref("test pcr plate", id=None, cont_type="96-pcr", discard=True) # generate seal and spin instructions that act on the ref # some parameters are explicitly specified and others are left to vendor defaults p.seal( ref=plate, type="foil", mode="thermal", temperature="165:celsius", duration="1.5:seconds" ) p.spin( ref=plate, acceleration="1000:g", duration="1:minute" ) # serialize the protocol as Autoprotocol JSON print(json.dumps(p.as_dict(), indent=2))
Starred by 124 users
Forked by 44 users
Languages   Python 100.0% | Python 100.0%
🌐
GitHub
github.com › googleapis › proto-plus-python
GitHub - googleapis/proto-plus-python: Beautiful, idiomatic protocol buffers in Python
This is a wrapper around protocol buffers. Protocol buffers is a specification format for APIs, such as those inside Google. This library provides protocol buffer message classes and objects that largely behave like native Python types.
Starred by 186 users
Forked by 37 users
Languages   Python 100.0% | Python 100.0%
🌐
Scipion-em
scipion-em.github.io › docs › release-3.0.0 › docs › developer › creating-a-protocol.html
Creating a protocol — Scipion 3.0.0 documentation
Steps list: Prepares the list of steps that will be executed in order to complete the protocol. Steps functions: Contains the code that will be executed (Python code or calls to external programs)
🌐
Real Python
realpython.com › python-protocol
Python Protocols: Leveraging Structural Subtyping – Real Python
July 25, 2024 - In this tutorial, you'll learn about Python's protocols and how they can help you get the most out of using Python's type hint system and static type checkers.
🌐
GitHub
github.com › danielgtaylor › python-betterproto
GitHub - danielgtaylor/python-betterproto: Clean, modern, Python 3.6+ code generator & library for Protobuf 3 and async gRPC
pip install grpcio-tools python -m grpc_tools.protoc -I . --python_betterproto_out=lib example.proto · This will generate lib/hello/__init__.py which looks like: # Generated by the protocol buffer compiler. DO NOT EDIT!
Starred by 1.8K users
Forked by 230 users
Languages   Python 95.2% | Jinja 3.1% | Java 1.7% | Python 95.2% | Jinja 3.1% | Java 1.7%
🌐
GitHub
github.com › protocolbuffers › protobuf › issues › 23670
[python] Message constructor argument enum typing · Issue #23670 · protocolbuffers/protobuf
September 27, 2025 - What version of protobuf and what language are you using? Version: main Language: Python What did you do? Steps to reproduce the behavior: Create a message with an enum Generate python and type stubs Create a message instance, and pass i...
Author   aidandj
🌐
GitHub
github.com › MarshalX › atproto
GitHub - MarshalX/atproto: The AT Protocol (🦋 Bluesky) SDK for Python 🐍
Python 3.9 or higher. ... First of all, you need to create the instance of the XRPC Client. To do so, you have two major options: asynchronous and synchronous. The difference is only in the import and how you call the methods. If you are not familiar with async, use sync instead. ... from atproto import Client client = Client() # By default, it uses the server of bsky.social. To change this behavior, pass the base api URL to constructor # Client('https://example.com')
Starred by 644 users
Forked by 76 users
Languages   Python
🌐
Python Tutorial
pythontutorial.net › home › python oop › python protocol
Python Protocol - Python Tutorial
March 31, 2025 - In this tutorial, you'll learn about the Python Protocol and its use to define implicit interfaces.
🌐
GitHub
github.com › simplesteph › protobuf-example-python
GitHub - simplesteph/protobuf-example-python: Companion Repository for my Protocol Buffers course · GitHub
Companion Repository for my Protocol Buffers course - simplesteph/protobuf-example-python
Starred by 48 users
Forked by 32 users
Languages   Python 91.4% | Shell 8.6%