Protocols don't allow that, because it breaks subtype transitivity. See PEP 544.

If you have the following two classes:

class A:
    def method(self, arg: int):
        pass

class B(A):
    def method(self, arg: object):
        pass

then B is a valid subclass of A, because B.method can accept any arguments A.method can. However, if you could introduce the following protocol:

T = typing.TypeVar('T')

class Proto(typing.Protocol[T]):
    def method(self, arg: T):
        pass

then A would satisfy Proto[int], but B would not, due to the invariance of T.

Answer from user2357112 on Stack Overflow
🌐
Python
typing.python.org › en › latest › spec › protocol.html
Protocols — typing documentation
Generic protocols follow the rules for generic abstract classes, except for using structural assignability instead of assignability defined by inheritance relationships. Static type checkers will recognize protocol implementations, even if the corresponding protocols are not imported: # file lib.py from collections.abc import Sized class ListLike[T](Sized, Protocol): def append(self, x: T) -> None: pass def populate(lst: ListLike[int]) -> None: ...
🌐
Python
peps.python.org › pep-0544
PEP 544 – Protocols: Structural subtyping (static duck typing) | peps.python.org
March 5, 2017 - Protocols can be used to define flexible callback types that are hard (or even impossible) to express using the Callable[...] syntax specified by PEP 484, such as variadic, overloaded, and complex generic callbacks. They can be defined as protocols with a __call__ member: from typing import Optional, List, Protocol class Combiner(Protocol): def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> List[bytes]: ...
Discussions

How do I create a generic interface in Python? - Stack Overflow
Why the protocol needs a contravariant variable? And, how do I make this Python code type check? More on stackoverflow.com
🌐 stackoverflow.com
Python generic type that implements protocol - Stack Overflow
Objects A, B ... have attribute namespace and I have a function that filters a list of such objects by a certain set of values of namespace attribute: T = TypeVar('T') def filter(seq: list[T], More on stackoverflow.com
🌐 stackoverflow.com
Issue with generic Protocol
There was an error while loading. Please reload this page · and Pyright see it as a valid code so I think it should be seen as valid by mypy More on github.com
🌐 github.com
2
February 15, 2022
Variance of arguments for Generic ABC vs Generic Protocol
I am trying to define a Generic base class, but see different type checking behavior when I inherit from abc.ABC versus Protocol. I am trying to figure out if it is really a difference of variance ... More on github.com
🌐 github.com
1
1
July 9, 2024
🌐
mypy
mypy.readthedocs.io › en › latest › generics.html
Generics - mypy 1.20.0+dev.acfef9c84da69805f740e67b108910888d66f7ab documentation
Here is the same example using the old syntax (required for Python 3.11 and earlier, but also supported on newer Python versions): from typing import TypeVar, Generic T = TypeVar('T') # Define type variable "T" class Stack(Generic[T]): def __init__(self) -> None: # Create an empty list with items of type T self.items: list[T] = [] def push(self, item: T) -> None: self.items.append(item) def pop(self) -> T: return self.items.pop() def empty(self) -> bool: return not self.items
🌐
Python
typing.python.org › en › latest › reference › generics.html
Generics — typing documentation
This is because these classes are nominally typed, unlike protocols like Iterable, which use structural subtyping. Generic can be omitted from bases if there are other base classes that include type variables, such as Mapping[KT, VT] in the above example. If you include Generic[...] in bases, then it should list ...
🌐
Real Python
realpython.com › python-protocol
Python Protocols: Leveraging Structural Subtyping – Real Python
July 25, 2024 - In this example, you first define a generic type for your protocol. You use the bound argument to state that the generic type can be an int or float object. Then, you have your concrete adders. In this case, you have IntAdder and FloatAdder to sum numbers. If you’re using Python 3.12, then you can use a simplified syntax:
🌐
Mypy
mypy.readthedocs.io › en › stable › generics.html
Generics - mypy 1.19.1 documentation
Here is the same example using the old syntax (required for Python 3.11 and earlier, but also supported on newer Python versions): from typing import TypeVar, Generic T = TypeVar('T') # Define type variable "T" class Stack(Generic[T]): def __init__(self) -> None: # Create an empty list with items of type T self.items: list[T] = [] def push(self, item: T) -> None: self.items.append(item) def pop(self) -> T: return self.items.pop() def empty(self) -> bool: return not self.items
Find elsewhere
🌐
Mypy
mypy.readthedocs.io › en › stable › protocols.html
Protocols and structural subtyping - mypy 1.19.1 documentation
Protocols can be used to define ... complex generic callbacks. They are defined with a special __call__ member: from collections.abc import Iterable from typing import Optional, Protocol class Combiner(Protocol): def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...
🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
1 month ago - Changed in version 3.12: Syntactic support for generics is new in Python 3.12. For most containers in Python, the typing system assumes that all elements in the container will be of the same type. For example: from collections.abc import Mapping # Type checker will infer that all elements in ``x`` are meant to be ints x: list[int] = [] # Type checker error: ``list`` only accepts a single type argument: y: list[int, str] = [1, 'foo'] # Type checker will infer that all keys in ``z`` are meant to be strings, # and that all values in ``z`` are meant to be either strings or ints z: Mapping[str, str | int] = {}
🌐
Auth0
auth0.com › blog › protocol-types-in-python
Protocol Types in Python 3.8
June 23, 2021 - Protocol is a very generic word, both in regular language as well as in Computer Science. Most of us are probably familiar with it from hearing TCP Protocol, UDP Protocol or also HTTP Protocol.
🌐
GitHub
github.com › python › typing › discussions › 1739
Generic Protocol with method taking instance of Protocol (e.g. Functor) · python/typing · Discussion #1739
May 17, 2024 - class Applicative(Functor[A], Protocol[A]): @staticmethod def pure(x: Any) -> Applicative[A]: ... @staticmethod def ap(f: Applicative[Callable[[A], B]], x: Applicative[A]) -> Applicative[B]: ... class Monad(Applicative[A], Protocol[A]): @staticmethod def bind(x: Monad[A], f: Callable[[A], Monad[B]]) -> Monad[B]: ... @dataclass class Io(Generic[A]): action: Callable[[], A] @staticmethod def fmap(f: Callable[[A], B], x: Io[A]) -> Io[B]: return Io(lambda: f(x.action())) @staticmethod def pure(x: A) -> Io[A]: return Io(lambda: x) @staticmethod def ap(f: Io[Callable[[A], B]], x: Io[A]) -> Io[B]: return Io(lambda: f.action()(x.action())) @staticmethod def bind(x: Io[A], f: Callable[[A], Io[B]]) -> Io[B]: return Io(lambda: f(x.action()).action()) def taking_monad(x: Monad[int]) -> bool: return True taking_monad(Io(lambda: 1))
Author   python
🌐
Medium
medium.com › @commbigo › python-typing-protocol-c2f6a60c0ac6
Python typing — Protocol
December 28, 2023 - from typing import Protocol, TypeVar, Generic T = TypeVar("T") class Job(Protocol[T]): def run(self, info: T) -> T: print(f"run the job {info}") return info class Job1(): def run(self, info: str) -> str: print(f"run the job1 {info}") return info def run_job(job: Job): job.run("test") job1: Job[str] = Job1() run_job(job1)
🌐
Python
typing.python.org › en › latest › reference › protocols.html
Protocols and structural subtyping — typing documentation
Protocols can be used to define ... and complex generic callbacks. They are defined with a special __call__ member: from typing import Optional, Iterable, Protocol class Combiner(Protocol): def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> list[bytes]: ...
🌐
Turingtaco
turingtaco.com › protocols-default-methods-inheritance-and-more
Protocols: Default Methods, Inheritance, and More
December 7, 2024 - The use of implicit type variables in Generic Protocols is also reflected in Python's standard library, as seen with Protocols like Iterable and Iterator.
🌐
GitHub
github.com › python › mypy › issues › 12183
Issue with generic Protocol · Issue #12183 · python/mypy
February 15, 2022 - from dataclasses import dataclass from typing import Generic, Protocol, TypeVar import pandas as pd _DataFrameBound = TypeVar("_DataFrameBound", bound=pd.DataFrame, covariant=True) class _Method(Protocol[_DataFrameBound]): def __call__(self, ...
Author   bloussou
🌐
GitHub
github.com › python › typing › discussions › 1793
Variance of arguments for Generic ABC vs Generic Protocol · python/typing · Discussion #1793
July 9, 2024 - import abc from typing import Generic, Protocol, TypedDict, TypeVar class BaseResult(TypedDict): """ Result """ R = TypeVar("R", bound=BaseResult) R_contra = TypeVar("R_contra", bound=BaseResult, contravariant=True) class BadProtocolResultWriter(Protocol[R]): """ Type variable "R" used in generic protocol "ProtocolResultWriter" should be contravariant (reportInvalidTypeVarUse) main.py:16: error: Invariant type variable "R" used in protocol where contravariant one is expected [misc] """ @abc.abstractmethod def write( self, result: R, ) -> None: """ Write to destination """ class ABCResultWriter(abc.ABC, Generic[R]): """ This type checks just fine, but what is different compared to the Protocol equivalent?
Author   python
🌐
Medium
medium.com › @sunilnepali844 › the-complete-guide-to-python-generics-from-beginner-to-pro-1d11d19b474c
The Complete Guide to Python Generics: From Beginner to Pro | by Sunil Nepali | Medium
August 26, 2025 - They are used with type hints introduced in Python 3.5+ (via the typing module) and Python 3.9+ (updated syntax). Generics allow you to define classes, functions, and data structures that can work with any type, but still let you specify which type will be used when the class/function is instantiated.
🌐
GitHub
github.com › python › mypy › issues › 5872
classmethod's in generic protocols with self-types · Issue #5872 · python/mypy
November 6, 2018 - from dataclasses import dataclass from typing import Union, ClassVar, TypeVar, Generic, Type from typing_extensions import Protocol _P = TypeVar('_P', bound='PType') class PType(Protocol): @classmethod def maximum_type_value(cls: Type[_P]) -> ...
Author   juanarrivillaga
🌐
Medium
medium.com › @shane-zhang › python-adventure-demystifying-generic-types-e7a1b64b75ed
Python Adventure: Demystifying Generic Types | by Shane Zhang | Medium
November 21, 2024 - A protocol defines what methods and behaviors a class must have, but it doesn’t need to be explicitly inherited. As long as the object follows the “rules” (method signatures), it is treated as a valid implementation, even if it’s not a subclass. This is duck typing in action! My first impression of TypeVar and Generic in Python ...