python-peps/pep-0544/index.html

1630 lines
155 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 544 Protocols: Structural subtyping (static duck typing) | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0544/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 544 Protocols: Structural subtyping (static duck typing) | peps.python.org'>
<meta property="og:description" content="Type hints introduced in PEP 484 can be used to specify type metadata for static type checkers and other third party tools. However, PEP 484 only specifies the semantics of nominal subtyping. In this PEP we specify static and runtime semantics of protoc...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0544/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Type hints introduced in PEP 484 can be used to specify type metadata for static type checkers and other third party tools. However, PEP 484 only specifies the semantics of nominal subtyping. In this PEP we specify static and runtime semantics of protoc...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 544</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 544 Protocols: Structural subtyping (static duck typing)</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Ivan Levkivskyi &lt;levkivskyi&#32;&#97;t&#32;gmail.com&gt;, Jukka Lehtosalo &lt;jukka.lehtosalo&#32;&#97;t&#32;iki.fi&gt;, Łukasz Langa &lt;lukasz&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/">Python-Dev list</a></dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/typing/">Typing</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">05-Mar-2017</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">3.8</dd>
<dt class="field-odd">Resolution<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/typing-sig&#64;python.org/message/FDO4KFYWYQEP3U2HVVBEBR3SXPHQSHYR/">Typing-SIG message</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a><ul>
<li><a class="reference internal" href="#nominal-vs-structural-subtyping">Nominal vs structural subtyping</a></li>
<li><a class="reference internal" href="#non-goals">Non-goals</a></li>
</ul>
</li>
<li><a class="reference internal" href="#existing-approaches-to-structural-subtyping">Existing Approaches to Structural Subtyping</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#terminology">Terminology</a></li>
<li><a class="reference internal" href="#defining-a-protocol">Defining a protocol</a></li>
<li><a class="reference internal" href="#protocol-members">Protocol members</a></li>
<li><a class="reference internal" href="#explicitly-declaring-implementation">Explicitly declaring implementation</a></li>
<li><a class="reference internal" href="#merging-and-extending-protocols">Merging and extending protocols</a></li>
<li><a class="reference internal" href="#generic-protocols">Generic protocols</a></li>
<li><a class="reference internal" href="#recursive-protocols">Recursive protocols</a></li>
<li><a class="reference internal" href="#self-types-in-protocols">Self-types in protocols</a></li>
<li><a class="reference internal" href="#callback-protocols">Callback protocols</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-protocols">Using Protocols</a><ul>
<li><a class="reference internal" href="#subtyping-relationships-with-other-types">Subtyping relationships with other types</a></li>
<li><a class="reference internal" href="#unions-and-intersections-of-protocols">Unions and intersections of protocols</a></li>
<li><a class="reference internal" href="#type-and-class-objects-vs-protocols"><code class="docutils literal notranslate"><span class="pre">Type[]</span></code> and class objects vs protocols</a></li>
<li><a class="reference internal" href="#newtype-and-type-aliases"><code class="docutils literal notranslate"><span class="pre">NewType()</span></code> and type aliases</a></li>
<li><a class="reference internal" href="#modules-as-implementations-of-protocols">Modules as implementations of protocols</a></li>
<li><a class="reference internal" href="#runtime-checkable-decorator-and-narrowing-types-by-isinstance"><code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code> decorator and narrowing types by <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-protocols-in-python-2-7-3-5">Using Protocols in Python 2.7 - 3.5</a></li>
<li><a class="reference internal" href="#runtime-implementation-of-protocol-classes">Runtime Implementation of Protocol Classes</a><ul>
<li><a class="reference internal" href="#implementation-details">Implementation details</a></li>
<li><a class="reference internal" href="#changes-in-the-typing-module">Changes in the typing module</a></li>
<li><a class="reference internal" href="#introspection">Introspection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rejected-postponed-ideas">Rejected/Postponed Ideas</a><ul>
<li><a class="reference internal" href="#make-every-class-a-protocol-by-default">Make every class a protocol by default</a></li>
<li><a class="reference internal" href="#protocols-subclassing-normal-classes">Protocols subclassing normal classes</a></li>
<li><a class="reference internal" href="#support-optional-protocol-members">Support optional protocol members</a></li>
<li><a class="reference internal" href="#allow-only-protocol-methods-and-force-use-of-getters-and-setters">Allow only protocol methods and force use of getters and setters</a></li>
<li><a class="reference internal" href="#support-non-protocol-members">Support non-protocol members</a></li>
<li><a class="reference internal" href="#make-protocols-interoperable-with-other-approaches">Make protocols interoperable with other approaches</a></li>
<li><a class="reference internal" href="#use-assignments-to-check-explicitly-that-a-class-implements-a-protocol">Use assignments to check explicitly that a class implements a protocol</a></li>
<li><a class="reference internal" href="#support-isinstance-checks-by-default">Support <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> checks by default</a></li>
<li><a class="reference internal" href="#provide-a-special-intersection-type-construct">Provide a special intersection type construct</a></li>
<li><a class="reference internal" href="#prohibit-explicit-subclassing-of-protocols-by-non-protocols">Prohibit explicit subclassing of protocols by non-protocols</a></li>
<li><a class="reference internal" href="#covariant-subtyping-of-mutable-attributes">Covariant subtyping of mutable attributes</a></li>
<li><a class="reference internal" href="#overriding-inferred-variance-of-protocol-classes">Overriding inferred variance of protocol classes</a></li>
<li><a class="reference internal" href="#support-adapters-and-adaptation">Support adapters and adaptation</a></li>
<li><a class="reference internal" href="#call-structural-base-types-interfaces">Call structural base types “interfaces”</a></li>
<li><a class="reference internal" href="#make-protocols-special-objects-at-runtime-rather-than-normal-abcs">Make protocols special objects at runtime rather than normal ABCs</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<div class="pep-banner canonical-typing-spec sticky-banner admonition attention">
<p class="admonition-title">Attention</p>
<p>This PEP is a historical document: see <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/protocol.html#protocols" title="(in typing)"><span>Protocols</span></a> and
<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Protocol" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">typing.Protocol</span></code></a> for up-to-date specs and documentation. Canonical typing specs are maintained at the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/">typing specs site</a>; runtime typing behaviour is described in the CPython documentation.</p>
<p class="close-button">×</p>
<p>See the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/meta.html">typing specification update process</a> for how to propose changes to the typing spec.</p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Type hints introduced in <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> can be used to specify type metadata
for static type checkers and other third party tools. However, <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>
only specifies the semantics of <em>nominal</em> subtyping. In this PEP we specify
static and runtime semantics of protocol classes that will provide a support
for <em>structural</em> subtyping (static duck typing).</p>
</section>
<section id="rationale-and-goals">
<span id="pep-544-rationale"></span><h2><a class="toc-backref" href="#rationale-and-goals" role="doc-backlink">Rationale and Goals</a></h2>
<p>Currently, <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> and the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module <a class="reference internal" href="#typing" id="id1"><span>[typing]</span></a> define abstract
base classes for several common Python protocols such as <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> and
<code class="docutils literal notranslate"><span class="pre">Sized</span></code>. The problem with them is that a class has to be explicitly marked
to support them, which is unpythonic and unlike what one would
normally do in idiomatic dynamically typed Python code. For example,
this conforms to <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Sized</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Iterator</span>
<span class="k">class</span> <span class="nc">Bucket</span><span class="p">(</span><span class="n">Sized</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">[</span><span class="nb">int</span><span class="p">]):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterator</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span> <span class="o">...</span>
</pre></div>
</div>
<p>The same problem appears with user-defined ABCs: they must be explicitly
subclassed or registered. This is particularly difficult to do with library
types as the type objects may be hidden deep in the implementation
of the library. Also, extensive use of ABCs might impose additional
runtime costs.</p>
<p>The intention of this PEP is to solve all these problems
by allowing users to write the above code without explicit base classes in
the class definition, allowing <code class="docutils literal notranslate"><span class="pre">Bucket</span></code> to be implicitly considered
a subtype of both <code class="docutils literal notranslate"><span class="pre">Sized</span></code> and <code class="docutils literal notranslate"><span class="pre">Iterable[int]</span></code> by static type checkers
using structural <a class="reference internal" href="#wiki-structural" id="id2"><span>[wiki-structural]</span></a> subtyping:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Iterator</span><span class="p">,</span> <span class="n">Iterable</span>
<span class="k">class</span> <span class="nc">Bucket</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterator</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span> <span class="o">...</span>
<span class="k">def</span> <span class="nf">collect</span><span class="p">(</span><span class="n">items</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="n">result</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">collect</span><span class="p">(</span><span class="n">Bucket</span><span class="p">())</span> <span class="c1"># Passes type check</span>
</pre></div>
</div>
<p>Note that ABCs in <code class="docutils literal notranslate"><span class="pre">typing</span></code> module already provide structural behavior
at runtime, <code class="docutils literal notranslate"><span class="pre">isinstance(Bucket(),</span> <span class="pre">Iterable)</span></code> returns <code class="docutils literal notranslate"><span class="pre">True</span></code>.
The main goal of this proposal is to support such behavior statically.
The same functionality will be provided for user-defined protocols, as
specified below. The above code with a protocol class matches common Python
conventions much better. It is also automatically extensible and works
with additional, unrelated classes that happen to implement
the required protocol.</p>
<section id="nominal-vs-structural-subtyping">
<h3><a class="toc-backref" href="#nominal-vs-structural-subtyping" role="doc-backlink">Nominal vs structural subtyping</a></h3>
<p>Structural subtyping is natural for Python programmers since it matches
the runtime semantics of duck typing: an object that has certain properties
is treated independently of its actual runtime class.
However, as discussed in <a class="pep reference internal" href="../pep-0483/" title="PEP 483 The Theory of Type Hints">PEP 483</a>, both nominal and structural
subtyping have their strengths and weaknesses. Therefore, in this PEP we
<em>do not propose</em> to replace the nominal subtyping described by <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> with
structural subtyping completely. Instead, protocol classes as specified in
this PEP complement normal classes, and users are free to choose
where to apply a particular solution. See section on <a class="reference internal" href="#pep-544-rejected">rejected</a> ideas at the end of this PEP for additional motivation.</p>
</section>
<section id="non-goals">
<h3><a class="toc-backref" href="#non-goals" role="doc-backlink">Non-goals</a></h3>
<p>At runtime, protocol classes will be simple ABCs. There is no intent to
provide sophisticated runtime instance and class checks against protocol
classes. This would be difficult and error-prone and will contradict the logic
of <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>. As well, following <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> and <a class="pep reference internal" href="../pep-0526/" title="PEP 526 Syntax for Variable Annotations">PEP 526</a> we state that protocols are
<strong>completely optional</strong>:</p>
<ul class="simple">
<li>No runtime semantics will be imposed for variables or parameters annotated
with a protocol class.</li>
<li>Any checks will be performed only by third-party type checkers and
other tools.</li>
<li>Programmers are free to not use them even if they use type annotations.</li>
<li>There is no intent to make protocols non-optional in the future.</li>
</ul>
<p>To reiterate, providing complex runtime semantics for protocol classes
is not a goal of this PEP, the main goal is to provide a support and standards
for <em>static</em> structural subtyping. The possibility to use protocols
in the runtime context as ABCs is rather a minor bonus that exists mostly
to provide a seamless transition for projects that already use ABCs.</p>
</section>
</section>
<section id="existing-approaches-to-structural-subtyping">
<h2><a class="toc-backref" href="#existing-approaches-to-structural-subtyping" role="doc-backlink">Existing Approaches to Structural Subtyping</a></h2>
<p>Before describing the actual specification, we review and comment on existing
approaches related to structural subtyping in Python and other languages:</p>
<ul>
<li><code class="docutils literal notranslate"><span class="pre">zope.interface</span></code> <a class="reference internal" href="#zope-interfaces" id="id3"><span>[zope-interfaces]</span></a> was one of the first widely used
approaches to structural subtyping in Python. It is implemented by providing
special classes to distinguish interface classes from normal classes,
to mark interface attributes, and to explicitly declare implementation.
For example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">zope.interface</span> <span class="kn">import</span> <span class="n">Interface</span><span class="p">,</span> <span class="n">Attribute</span><span class="p">,</span> <span class="n">implementer</span>
<span class="k">class</span> <span class="nc">IEmployee</span><span class="p">(</span><span class="n">Interface</span><span class="p">):</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">Attribute</span><span class="p">(</span><span class="s2">&quot;Name of employee&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do</span><span class="p">(</span><span class="n">work</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Do some work&quot;&quot;&quot;</span>
<span class="nd">@implementer</span><span class="p">(</span><span class="n">IEmployee</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Employee</span><span class="p">:</span>
<span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;Anonymous&#39;</span>
<span class="k">def</span> <span class="nf">do</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">work</span><span class="p">):</span>
<span class="k">return</span> <span class="n">work</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</pre></div>
</div>
<p>Zope interfaces support various contracts and constraints for interface
classes. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">zope.interface</span> <span class="kn">import</span> <span class="n">invariant</span>
<span class="k">def</span> <span class="nf">required_contact</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">email</span> <span class="ow">or</span> <span class="n">obj</span><span class="o">.</span><span class="n">phone</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;At least one contact info is required&quot;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">IPerson</span><span class="p">(</span><span class="n">Interface</span><span class="p">):</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">Attribute</span><span class="p">(</span><span class="s2">&quot;Name&quot;</span><span class="p">)</span>
<span class="n">email</span> <span class="o">=</span> <span class="n">Attribute</span><span class="p">(</span><span class="s2">&quot;Email Address&quot;</span><span class="p">)</span>
<span class="n">phone</span> <span class="o">=</span> <span class="n">Attribute</span><span class="p">(</span><span class="s2">&quot;Phone Number&quot;</span><span class="p">)</span>
<span class="n">invariant</span><span class="p">(</span><span class="n">required_contact</span><span class="p">)</span>
</pre></div>
</div>
<p>Even more detailed invariants are supported. However, Zope interfaces rely
entirely on runtime validation. Such focus on runtime properties goes
beyond the scope of the current proposal, and static support for invariants
might be difficult to implement. However, the idea of marking an interface
class with a special base class is reasonable and easy to implement both
statically and at runtime.</p>
</li>
<li>Python abstract base classes <a class="reference internal" href="#abstract-classes" id="id4"><span>[abstract-classes]</span></a> are the standard
library tool to provide some functionality similar to structural subtyping.
The drawback of this approach is the necessity to either subclass
the abstract class or register an implementation explicitly:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">ABC</span>
<span class="k">class</span> <span class="nc">MyTuple</span><span class="p">(</span><span class="n">ABC</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">MyTuple</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">tuple</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="n">MyTuple</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">((),</span> <span class="n">MyTuple</span><span class="p">)</span>
</pre></div>
</div>
<p>As mentioned in the <a class="reference internal" href="#pep-544-rationale">rationale</a>,
we want to avoid such necessity, especially in static context.
However, in a runtime context, ABCs are good candidates for
protocol classes and they are already used extensively in
the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module.</p>
</li>
<li>Abstract classes defined in <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> module <a class="reference internal" href="#collections-abc" id="id5"><span>[collections-abc]</span></a>
are slightly more advanced since they implement a custom
<code class="docutils literal notranslate"><span class="pre">__subclasshook__()</span></code> method that allows runtime structural checks without
explicit registration:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">collections.abc</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="k">class</span> <span class="nc">MyIterable</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="p">[]</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">MyIterable</span><span class="p">(),</span> <span class="n">Iterable</span><span class="p">)</span>
</pre></div>
</div>
<p>Such behavior seems to be a perfect fit for both runtime and static behavior
of protocols. As discussed in <a class="reference internal" href="#pep-544-rationale">rationale</a>,
we propose to add static support for such behavior.
In addition, to allow users to achieve such runtime
behavior for <em>user-defined</em> protocols a special <code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code> decorator
will be provided, see detailed <a class="reference internal" href="#discussion">discussion</a> below.</p>
</li>
<li>TypeScript <a class="reference internal" href="#typescript" id="id6"><span>[typescript]</span></a> provides support for user-defined classes and
interfaces. Explicit implementation declaration is not required and
structural subtyping is verified statically. For example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>interface LabeledItem {
label: string;
size?: int;
}
function printLabel(obj: LabeledItem) {
console.log(obj.label);
}
let myObj = {size: 10, label: &quot;Size 10 Object&quot;};
printLabel(myObj);
</pre></div>
</div>
<p>Note that optional interface members are supported. Also, TypeScript
prohibits redundant members in implementations. While the idea of
optional members looks interesting, it would complicate this proposal and
it is not clear how useful it will be. Therefore, it is proposed to postpone
this; see <a class="reference internal" href="#pep-544-rejected">rejected</a> ideas. In general, the idea of
static protocol checking without runtime implications looks reasonable,
and basically this proposal follows the same line.</p>
</li>
<li>Go <a class="reference internal" href="#golang" id="id7"><span>[golang]</span></a> uses a more radical approach and makes interfaces the primary
way to provide type information. Also, assignments are used to explicitly
ensure implementation:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">type</span> <span class="n">SomeInterface</span> <span class="n">interface</span> <span class="p">{</span>
<span class="n">SomeMethod</span><span class="p">()</span> <span class="p">([]</span><span class="n">byte</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">if</span> <span class="n">_</span><span class="p">,</span> <span class="n">ok</span> <span class="o">:=</span> <span class="n">someval</span><span class="o">.</span><span class="p">(</span><span class="n">SomeInterface</span><span class="p">);</span> <span class="n">ok</span> <span class="p">{</span>
<span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s2">&quot;value implements some interface&quot;</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Both these ideas are questionable in the context of this proposal. See
the section on <a class="reference internal" href="#pep-544-rejected">rejected</a> ideas.</p>
</li>
</ul>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<section id="terminology">
<h3><a class="toc-backref" href="#terminology" role="doc-backlink">Terminology</a></h3>
<p>We propose to use the term <em>protocols</em> for types supporting structural
subtyping. The reason is that the term <em>iterator protocol</em>,
for example, is widely understood in the community, and coming up with
a new term for this concept in a statically typed context would just create
confusion.</p>
<p>This has the drawback that the term <em>protocol</em> becomes overloaded with
two subtly different meanings: the first is the traditional, well-known but
slightly fuzzy concept of protocols such as iterator; the second is the more
explicitly defined concept of protocols in statically typed code.
The distinction is not important most of the time, and in other
cases we propose to just add a qualifier such as <em>protocol classes</em>
when referring to the static type concept.</p>
<p>If a class includes a protocol in its MRO, the class is called
an <em>explicit</em> subclass of the protocol. If a class is a structural subtype
of a protocol, it is said to implement the protocol and to be compatible
with a protocol. If a class is compatible with a protocol but the protocol
is not included in the MRO, the class is an <em>implicit</em> subtype
of the protocol. (Note that one can explicitly subclass a protocol and
still not implement it if a protocol attribute is set to <code class="docutils literal notranslate"><span class="pre">None</span></code>
in the subclass, see Python <a class="reference internal" href="#data-model" id="id8"><span>[data-model]</span></a> for details.)</p>
<p>The attributes (variables and methods) of a protocol that are mandatory
for other class in order to be considered a structural subtype are called
protocol members.</p>
</section>
<section id="defining-a-protocol">
<span id="definition"></span><h3><a class="toc-backref" href="#defining-a-protocol" role="doc-backlink">Defining a protocol</a></h3>
<p>Protocols are defined by including a special new class <code class="docutils literal notranslate"><span class="pre">typing.Protocol</span></code>
(an instance of <code class="docutils literal notranslate"><span class="pre">abc.ABCMeta</span></code>) in the base classes list, typically
at the end of the list. Here is a simple example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">SupportsClose</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Now if one defines a class <code class="docutils literal notranslate"><span class="pre">Resource</span></code> with a <code class="docutils literal notranslate"><span class="pre">close()</span></code> method that has
a compatible signature, it would implicitly be a subtype of
<code class="docutils literal notranslate"><span class="pre">SupportsClose</span></code>, since the structural subtyping is used for
protocol types:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Resource</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
</pre></div>
</div>
<p>Apart from few restrictions explicitly mentioned below, protocol types can
be used in every context where a normal types can:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">close_all</span><span class="p">(</span><span class="n">things</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">SupportsClose</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">things</span><span class="p">:</span>
<span class="n">t</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;foo.txt&#39;</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">Resource</span><span class="p">()</span>
<span class="n">close_all</span><span class="p">([</span><span class="n">f</span><span class="p">,</span> <span class="n">r</span><span class="p">])</span> <span class="c1"># OK!</span>
<span class="n">close_all</span><span class="p">([</span><span class="mi">1</span><span class="p">])</span> <span class="c1"># Error: &#39;int&#39; has no &#39;close&#39; method</span>
</pre></div>
</div>
<p>Note that both the user-defined class <code class="docutils literal notranslate"><span class="pre">Resource</span></code> and the built-in
<code class="docutils literal notranslate"><span class="pre">IO</span></code> type (the return type of <code class="docutils literal notranslate"><span class="pre">open()</span></code>) are considered subtypes of
<code class="docutils literal notranslate"><span class="pre">SupportsClose</span></code>, because they provide a <code class="docutils literal notranslate"><span class="pre">close()</span></code> method with
a compatible type signature.</p>
</section>
<section id="protocol-members">
<h3><a class="toc-backref" href="#protocol-members" role="doc-backlink">Protocol members</a></h3>
<p>All methods defined in the protocol class body are protocol members, both
normal and decorated with <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code>. If any parameters of a
protocol method are not annotated, then their types are assumed to be <code class="docutils literal notranslate"><span class="pre">Any</span></code>
(see <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>). Bodies of protocol methods are type checked.
An abstract method that should not be called via <code class="docutils literal notranslate"><span class="pre">super()</span></code> ought to raise
<code class="docutils literal notranslate"><span class="pre">NotImplementedError</span></code>. Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Protocol</span>
<span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">abstractmethod</span>
<span class="k">class</span> <span class="nc">Example</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="c1"># This is a protocol member</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">second</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="c1"># Method without a default implementation</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
</pre></div>
</div>
<p>Static methods, class methods, and properties are equally allowed
in protocols.</p>
<p>To define a protocol variable, one can use <a class="pep reference internal" href="../pep-0526/" title="PEP 526 Syntax for Variable Annotations">PEP 526</a> variable
annotations in the class body. Additional attributes <em>only</em> defined in
the body of a method by assignment via <code class="docutils literal notranslate"><span class="pre">self</span></code> are not allowed. The rationale
for this is that the protocol class implementation is often not shared by
subtypes, so the interface should not depend on the default implementation.
Examples:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Protocol</span><span class="p">,</span> <span class="n">List</span>
<span class="k">class</span> <span class="nc">Template</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span> <span class="c1"># This is a protocol member</span>
<span class="n">value</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># This one too (with default)</span>
<span class="k">def</span> <span class="nf">method</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">temp</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># Error in type checker</span>
<span class="k">class</span> <span class="nc">Concrete</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">def</span> <span class="nf">method</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">var</span><span class="p">:</span> <span class="n">Template</span> <span class="o">=</span> <span class="n">Concrete</span><span class="p">(</span><span class="s1">&#39;value&#39;</span><span class="p">,</span> <span class="mi">42</span><span class="p">)</span> <span class="c1"># OK</span>
</pre></div>
</div>
<p>To distinguish between protocol class variables and protocol instance
variables, the special <code class="docutils literal notranslate"><span class="pre">ClassVar</span></code> annotation should be used as specified
by <a class="pep reference internal" href="../pep-0526/" title="PEP 526 Syntax for Variable Annotations">PEP 526</a>. By default, protocol variables as defined above are considered
readable and writable. To define a read-only protocol variable, one can use
an (abstract) property.</p>
</section>
<section id="explicitly-declaring-implementation">
<h3><a class="toc-backref" href="#explicitly-declaring-implementation" role="doc-backlink">Explicitly declaring implementation</a></h3>
<p>To explicitly declare that a certain class implements a given protocol,
it can be used as a regular base class. In this case a class could use
default implementations of protocol members. Static analysis tools are
expected to automatically detect that a class implements a given protocol.
So while its possible to subclass a protocol explicitly, its <em>not necessary</em>
to do so for the sake of type-checking.</p>
<p>The default implementations cannot be used if
the subtype relationship is implicit and only via structural
subtyping the semantics of inheritance is not changed. Examples:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">PColor</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">complex_method</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="c1"># some complex code here</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">NiceColor</span><span class="p">(</span><span class="n">PColor</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;deep blue&quot;</span>
<span class="k">class</span> <span class="nc">BadColor</span><span class="p">(</span><span class="n">PColor</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">draw</span><span class="p">()</span> <span class="c1"># Error, no default implementation</span>
<span class="k">class</span> <span class="nc">ImplicitColor</span><span class="p">:</span> <span class="c1"># Note no &#39;PColor&#39; base here</span>
<span class="k">def</span> <span class="nf">draw</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;probably gray&quot;</span>
<span class="k">def</span> <span class="nf">complex_method</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="c1"># class needs to implement this</span>
<span class="o">...</span>
<span class="n">nice</span><span class="p">:</span> <span class="n">NiceColor</span>
<span class="n">another</span><span class="p">:</span> <span class="n">ImplicitColor</span>
<span class="k">def</span> <span class="nf">represent</span><span class="p">(</span><span class="n">c</span><span class="p">:</span> <span class="n">PColor</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">draw</span><span class="p">(),</span> <span class="n">c</span><span class="o">.</span><span class="n">complex_method</span><span class="p">())</span>
<span class="n">represent</span><span class="p">(</span><span class="n">nice</span><span class="p">)</span> <span class="c1"># OK</span>
<span class="n">represent</span><span class="p">(</span><span class="n">another</span><span class="p">)</span> <span class="c1"># Also OK</span>
</pre></div>
</div>
<p>Note that there is little difference between explicit and implicit
subtypes, the main benefit of explicit subclassing is to get some protocol
methods “for free”. In addition, type checkers can statically verify that
the class actually implements the protocol correctly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">RGB</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="n">rgb</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">]</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">intensity</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="k">class</span> <span class="nc">Point</span><span class="p">(</span><span class="n">RGB</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">red</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">green</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">blue</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rgb</span> <span class="o">=</span> <span class="n">red</span><span class="p">,</span> <span class="n">green</span><span class="p">,</span> <span class="n">blue</span> <span class="c1"># Error, &#39;blue&#39; must be &#39;int&#39;</span>
<span class="c1"># Type checker might warn that &#39;intensity&#39; is not defined</span>
</pre></div>
</div>
<p>A class can explicitly inherit from multiple protocols and also from normal
classes. In this case methods are resolved using normal MRO and a type checker
verifies that all subtyping are correct. The semantics of <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code>
is not changed, all of them must be implemented by an explicit subclass
before it can be instantiated.</p>
</section>
<section id="merging-and-extending-protocols">
<h3><a class="toc-backref" href="#merging-and-extending-protocols" role="doc-backlink">Merging and extending protocols</a></h3>
<p>The general philosophy is that protocols are mostly like regular ABCs,
but a static type checker will handle them specially. Subclassing a protocol
class would not turn the subclass into a protocol unless it also has
<code class="docutils literal notranslate"><span class="pre">typing.Protocol</span></code> as an explicit base class. Without this base, the class
is “downgraded” to a regular ABC that cannot be used with structural
subtyping. The rationale for this rule is that we dont want to accidentally
have some class act as a protocol just because one of its base classes
happens to be one. We still slightly prefer nominal subtyping over structural
subtyping in the static typing world.</p>
<p>A subprotocol can be defined by having <em>both</em> one or more protocols as
immediate base classes and also having <code class="docutils literal notranslate"><span class="pre">typing.Protocol</span></code> as an immediate
base class:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Sized</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">SizedAndClosable</span><span class="p">(</span><span class="n">Sized</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Now the protocol <code class="docutils literal notranslate"><span class="pre">SizedAndClosable</span></code> is a protocol with two methods,
<code class="docutils literal notranslate"><span class="pre">__len__</span></code> and <code class="docutils literal notranslate"><span class="pre">close</span></code>. If one omits <code class="docutils literal notranslate"><span class="pre">Protocol</span></code> in the base class list,
this would be a regular (non-protocol) class that must implement <code class="docutils literal notranslate"><span class="pre">Sized</span></code>.
Alternatively, one can implement <code class="docutils literal notranslate"><span class="pre">SizedAndClosable</span></code> protocol by merging
the <code class="docutils literal notranslate"><span class="pre">SupportsClose</span></code> protocol from the example in the <a class="reference internal" href="#definition">definition</a> section
with <code class="docutils literal notranslate"><span class="pre">typing.Sized</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Sized</span>
<span class="k">class</span> <span class="nc">SupportsClose</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">SizedAndClosable</span><span class="p">(</span><span class="n">Sized</span><span class="p">,</span> <span class="n">SupportsClose</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>The two definitions of <code class="docutils literal notranslate"><span class="pre">SizedAndClosable</span></code> are equivalent.
Subclass relationships between protocols are not meaningful when
considering subtyping, since structural compatibility is
the criterion, not the MRO.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">Protocol</span></code> is included in the base class list, all the other base classes
must be protocols. A protocol cant extend a regular class, see <a class="reference internal" href="#pep-544-rejected">rejected</a> ideas for rationale.
Note that rules around explicit subclassing are different
from regular ABCs, where abstractness is simply defined by having at least one
abstract method being unimplemented. Protocol classes must be marked
<em>explicitly</em>.</p>
</section>
<section id="generic-protocols">
<h3><a class="toc-backref" href="#generic-protocols" role="doc-backlink">Generic protocols</a></h3>
<p>Generic protocols are important. For example, <code class="docutils literal notranslate"><span class="pre">SupportsAbs</span></code>, <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>
and <code class="docutils literal notranslate"><span class="pre">Iterator</span></code> are generic protocols. They are defined similar to normal
non-protocol generic types:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Iterable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterator</span><span class="p">[</span><span class="n">T</span><span class="p">]:</span>
<span class="o">...</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">Protocol[T,</span> <span class="pre">S,</span> <span class="pre">...]</span></code> is allowed as a shorthand for
<code class="docutils literal notranslate"><span class="pre">Protocol,</span> <span class="pre">Generic[T,</span> <span class="pre">S,</span> <span class="pre">...]</span></code>.</p>
<p>User-defined generic protocols support explicitly declared variance.
Type checkers will warn if the inferred variance is different from
the declared variance. Examples:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T&#39;</span><span class="p">)</span>
<span class="n">T_co</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T_co&#39;</span><span class="p">,</span> <span class="n">covariant</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">T_contra</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T_contra&#39;</span><span class="p">,</span> <span class="n">contravariant</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Box</span><span class="p">(</span><span class="n">Protocol</span><span class="p">[</span><span class="n">T_co</span><span class="p">]):</span>
<span class="k">def</span> <span class="nf">content</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T_co</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">box</span><span class="p">:</span> <span class="n">Box</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>
<span class="n">second_box</span><span class="p">:</span> <span class="n">Box</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>
<span class="n">box</span> <span class="o">=</span> <span class="n">second_box</span> <span class="c1"># This is OK due to the covariance of &#39;Box&#39;.</span>
<span class="k">class</span> <span class="nc">Sender</span><span class="p">(</span><span class="n">Protocol</span><span class="p">[</span><span class="n">T_contra</span><span class="p">]):</span>
<span class="k">def</span> <span class="nf">send</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">:</span> <span class="n">T_contra</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">sender</span><span class="p">:</span> <span class="n">Sender</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>
<span class="n">new_sender</span><span class="p">:</span> <span class="n">Sender</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>
<span class="n">new_sender</span> <span class="o">=</span> <span class="n">sender</span> <span class="c1"># OK, &#39;Sender&#39; is contravariant.</span>
<span class="k">class</span> <span class="nc">Proto</span><span class="p">(</span><span class="n">Protocol</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
<span class="n">attr</span><span class="p">:</span> <span class="n">T</span> <span class="c1"># this class is invariant, since it has a mutable attribute</span>
<span class="n">var</span><span class="p">:</span> <span class="n">Proto</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>
<span class="n">another_var</span><span class="p">:</span> <span class="n">Proto</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>
<span class="n">var</span> <span class="o">=</span> <span class="n">another_var</span> <span class="c1"># Error! &#39;Proto[float]&#39; is incompatible with &#39;Proto[int]&#39;.</span>
</pre></div>
</div>
<p>Note that unlike nominal classes, de facto covariant protocols cannot be
declared as invariant, since this can break transitivity of subtyping
(see <a class="reference internal" href="#pep-544-rejected">rejected</a> ideas for details). For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T&#39;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">AnotherBox</span><span class="p">(</span><span class="n">Protocol</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span> <span class="c1"># Error, this protocol is covariant in T,</span>
<span class="k">def</span> <span class="nf">content</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span> <span class="c1"># not invariant.</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
<section id="recursive-protocols">
<h3><a class="toc-backref" href="#recursive-protocols" role="doc-backlink">Recursive protocols</a></h3>
<p>Recursive protocols are also supported. Forward references to the protocol
class names can be given as strings as specified by <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>. Recursive
protocols are useful for representing self-referential data structures
like trees in an abstract fashion:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Traversable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">leaves</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterable</span><span class="p">[</span><span class="s1">&#39;Traversable&#39;</span><span class="p">]:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Note that for recursive protocols, a class is considered a subtype of
the protocol in situations where the decision depends on itself.
Continuing the previous example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">SimpleTree</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">leaves</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="s1">&#39;SimpleTree&#39;</span><span class="p">]:</span>
<span class="o">...</span>
<span class="n">root</span><span class="p">:</span> <span class="n">Traversable</span> <span class="o">=</span> <span class="n">SimpleTree</span><span class="p">()</span> <span class="c1"># OK</span>
<span class="k">class</span> <span class="nc">Tree</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
<span class="k">def</span> <span class="nf">leaves</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="s1">&#39;Tree[T]&#39;</span><span class="p">]:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">walk</span><span class="p">(</span><span class="n">graph</span><span class="p">:</span> <span class="n">Traversable</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">tree</span><span class="p">:</span> <span class="n">Tree</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span> <span class="o">=</span> <span class="n">Tree</span><span class="p">()</span>
<span class="n">walk</span><span class="p">(</span><span class="n">tree</span><span class="p">)</span> <span class="c1"># OK, &#39;Tree[float]&#39; is a subtype of &#39;Traversable&#39;</span>
</pre></div>
</div>
</section>
<section id="self-types-in-protocols">
<h3><a class="toc-backref" href="#self-types-in-protocols" role="doc-backlink">Self-types in protocols</a></h3>
<p>The self-types in protocols follow the
<a class="pep reference internal" href="../pep-0484/#annotating-instance-and-class-methods" title="PEP 484 Type Hints § Annotating instance and class methods">corresponding specification</a>
of <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">C</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;C&#39;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s1">&#39;Copyable&#39;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Copyable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">C</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">C</span><span class="p">:</span>
<span class="k">class</span> <span class="nc">One</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s1">&#39;One&#39;</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T&#39;</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s1">&#39;Other&#39;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Other</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">c</span><span class="p">:</span> <span class="n">Copyable</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">One</span><span class="p">()</span> <span class="c1"># OK</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">Other</span><span class="p">()</span> <span class="c1"># Also OK</span>
</pre></div>
</div>
</section>
<section id="callback-protocols">
<h3><a class="toc-backref" href="#callback-protocols" role="doc-backlink">Callback protocols</a></h3>
<p>Protocols can be used to define flexible callback types that are hard
(or even impossible) to express using the <code class="docutils literal notranslate"><span class="pre">Callable[...]</span></code> syntax
specified by <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>, such as variadic, overloaded, and complex generic
callbacks. They can be defined as protocols with a <code class="docutils literal notranslate"><span class="pre">__call__</span></code> member:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">Combiner</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">vals</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span>
<span class="n">maxlen</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]:</span> <span class="o">...</span>
<span class="k">def</span> <span class="nf">good_cb</span><span class="p">(</span><span class="o">*</span><span class="n">vals</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">maxlen</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">bad_cb</span><span class="p">(</span><span class="o">*</span><span class="n">vals</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">maxitems</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]:</span>
<span class="o">...</span>
<span class="n">comb</span><span class="p">:</span> <span class="n">Combiner</span> <span class="o">=</span> <span class="n">good_cb</span> <span class="c1"># OK</span>
<span class="n">comb</span> <span class="o">=</span> <span class="n">bad_cb</span> <span class="c1"># Error! Argument 2 has incompatible type because of</span>
<span class="c1"># different name and kind in the callback</span>
</pre></div>
</div>
<p>Callback protocols and <code class="docutils literal notranslate"><span class="pre">Callable[...]</span></code> types can be used interchangeably.</p>
</section>
</section>
<section id="using-protocols">
<h2><a class="toc-backref" href="#using-protocols" role="doc-backlink">Using Protocols</a></h2>
<section id="subtyping-relationships-with-other-types">
<h3><a class="toc-backref" href="#subtyping-relationships-with-other-types" role="doc-backlink">Subtyping relationships with other types</a></h3>
<p>Protocols cannot be instantiated, so there are no values whose
runtime type is a protocol. For variables and parameters with protocol types,
subtyping relationships are subject to the following rules:</p>
<ul class="simple">
<li>A protocol is never a subtype of a concrete type.</li>
<li>A concrete type <code class="docutils literal notranslate"><span class="pre">X</span></code> is a subtype of protocol <code class="docutils literal notranslate"><span class="pre">P</span></code>
if and only if <code class="docutils literal notranslate"><span class="pre">X</span></code> implements all protocol members of <code class="docutils literal notranslate"><span class="pre">P</span></code> with
compatible types. In other words, subtyping with respect to a protocol is
always structural.</li>
<li>A protocol <code class="docutils literal notranslate"><span class="pre">P1</span></code> is a subtype of another protocol <code class="docutils literal notranslate"><span class="pre">P2</span></code> if <code class="docutils literal notranslate"><span class="pre">P1</span></code> defines
all protocol members of <code class="docutils literal notranslate"><span class="pre">P2</span></code> with compatible types.</li>
</ul>
<p>Generic protocol types follow the same rules of variance as non-protocol
types. Protocol types can be used in all contexts where any other types
can be used, such as in <code class="docutils literal notranslate"><span class="pre">Union</span></code>, <code class="docutils literal notranslate"><span class="pre">ClassVar</span></code>, type variables bounds, etc.
Generic protocols follow the rules for generic abstract classes, except for
using structural compatibility instead of compatibility defined by
inheritance relationships.</p>
<p>Static type checkers will recognize protocol implementations, even if the
corresponding protocols are <em>not imported</em>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># file lib.py</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Sized</span>
<span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T&#39;</span><span class="p">,</span> <span class="n">contravariant</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">ListLike</span><span class="p">(</span><span class="n">Sized</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
<span class="k">def</span> <span class="nf">append</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">populate</span><span class="p">(</span><span class="n">lst</span><span class="p">:</span> <span class="n">ListLike</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="c1"># file main.py</span>
<span class="kn">from</span> <span class="nn">lib</span> <span class="kn">import</span> <span class="n">populate</span> <span class="c1"># Note that ListLike is NOT imported</span>
<span class="k">class</span> <span class="nc">MockStack</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="k">def</span> <span class="nf">append</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">populate</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span> <span class="c1"># Passes type check</span>
<span class="n">populate</span><span class="p">(</span><span class="n">MockStack</span><span class="p">())</span> <span class="c1"># Also OK</span>
</pre></div>
</div>
</section>
<section id="unions-and-intersections-of-protocols">
<h3><a class="toc-backref" href="#unions-and-intersections-of-protocols" role="doc-backlink">Unions and intersections of protocols</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">Union</span></code> of protocol classes behaves the same way as for non-protocol
classes. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Union</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">Exitable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">exit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">Quittable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">quit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">finish</span><span class="p">(</span><span class="n">task</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">Exitable</span><span class="p">,</span> <span class="n">Quittable</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">DefaultJob</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">quit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="n">finish</span><span class="p">(</span><span class="n">DefaultJob</span><span class="p">())</span> <span class="c1"># OK</span>
</pre></div>
</div>
<p>One can use multiple inheritance to define an intersection of protocols.
Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Hashable</span>
<span class="k">class</span> <span class="nc">HashableFloats</span><span class="p">(</span><span class="n">Iterable</span><span class="p">[</span><span class="nb">float</span><span class="p">],</span> <span class="n">Hashable</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">cached_func</span><span class="p">(</span><span class="n">args</span><span class="p">:</span> <span class="n">HashableFloats</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">float</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">cached_func</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="c1"># OK, tuple is both hashable and iterable</span>
</pre></div>
</div>
<p>If this will prove to be a widely used scenario, then a special
intersection type construct could be added in future as specified by <a class="pep reference internal" href="../pep-0483/" title="PEP 483 The Theory of Type Hints">PEP 483</a>,
see <a class="reference internal" href="#pep-544-rejected">rejected</a> ideas for more details.</p>
</section>
<section id="type-and-class-objects-vs-protocols">
<h3><a class="toc-backref" href="#type-and-class-objects-vs-protocols" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">Type[]</span></code> and class objects vs protocols</a></h3>
<p>Variables and parameters annotated with <code class="docutils literal notranslate"><span class="pre">Type[Proto]</span></code> accept only concrete
(non-protocol) subtypes of <code class="docutils literal notranslate"><span class="pre">Proto</span></code>. The main reason for this is to allow
instantiation of parameters with such type. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Proto</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">Concrete</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">42</span>
<span class="k">def</span> <span class="nf">fun</span><span class="p">(</span><span class="bp">cls</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">Proto</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">cls</span><span class="p">()</span><span class="o">.</span><span class="n">meth</span><span class="p">()</span> <span class="c1"># OK</span>
<span class="n">fun</span><span class="p">(</span><span class="n">Proto</span><span class="p">)</span> <span class="c1"># Error</span>
<span class="n">fun</span><span class="p">(</span><span class="n">Concrete</span><span class="p">)</span> <span class="c1"># OK</span>
</pre></div>
</div>
<p>The same rule applies to variables:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">var</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">Proto</span><span class="p">]</span>
<span class="n">var</span> <span class="o">=</span> <span class="n">Proto</span> <span class="c1"># Error</span>
<span class="n">var</span> <span class="o">=</span> <span class="n">Concrete</span> <span class="c1"># OK</span>
<span class="n">var</span><span class="p">()</span><span class="o">.</span><span class="n">meth</span><span class="p">()</span> <span class="c1"># OK</span>
</pre></div>
</div>
<p>Assigning an ABC or a protocol class to a variable is allowed if it is
not explicitly typed, and such assignment creates a type alias.
For normal (non-abstract) classes, the behavior of <code class="docutils literal notranslate"><span class="pre">Type[]</span></code> is
not changed.</p>
<p>A class object is considered an implementation of a protocol if accessing
all members on it results in types compatible with the protocol members.
For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">ProtoA</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="k">class</span> <span class="nc">ProtoB</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="n">a</span><span class="p">:</span> <span class="n">ProtoA</span> <span class="o">=</span> <span class="n">C</span> <span class="c1"># Type check error, signatures don&#39;t match!</span>
<span class="n">b</span><span class="p">:</span> <span class="n">ProtoB</span> <span class="o">=</span> <span class="n">C</span> <span class="c1"># OK</span>
</pre></div>
</div>
</section>
<section id="newtype-and-type-aliases">
<h3><a class="toc-backref" href="#newtype-and-type-aliases" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">NewType()</span></code> and type aliases</a></h3>
<p>Protocols are essentially anonymous. To emphasize this point, static type
checkers might refuse protocol classes inside <code class="docutils literal notranslate"><span class="pre">NewType()</span></code> to avoid an
illusion that a distinct type is provided:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">NewType</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">,</span> <span class="n">Iterator</span>
<span class="k">class</span> <span class="nc">Id</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="n">code</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">secrets</span><span class="p">:</span> <span class="n">Iterator</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]</span>
<span class="n">UserId</span> <span class="o">=</span> <span class="n">NewType</span><span class="p">(</span><span class="s1">&#39;UserId&#39;</span><span class="p">,</span> <span class="n">Id</span><span class="p">)</span> <span class="c1"># Error, can&#39;t provide distinct type</span>
</pre></div>
</div>
<p>In contrast, type aliases are fully supported, including generic type
aliases:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Reversible</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Sized</span>
<span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T&#39;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">SizedIterable</span><span class="p">(</span><span class="n">Iterable</span><span class="p">[</span><span class="n">T</span><span class="p">],</span> <span class="n">Sized</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">CompatReversible</span> <span class="o">=</span> <span class="n">Union</span><span class="p">[</span><span class="n">Reversible</span><span class="p">[</span><span class="n">T</span><span class="p">],</span> <span class="n">SizedIterable</span><span class="p">[</span><span class="n">T</span><span class="p">]]</span>
</pre></div>
</div>
</section>
<section id="modules-as-implementations-of-protocols">
<h3><a class="toc-backref" href="#modules-as-implementations-of-protocols" role="doc-backlink">Modules as implementations of protocols</a></h3>
<p>A module object is accepted where a protocol is expected if the public
interface of the given module is compatible with the expected protocol.
For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># file default_config.py</span>
<span class="n">timeout</span> <span class="o">=</span> <span class="mi">100</span>
<span class="n">one_flag</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">other_flag</span> <span class="o">=</span> <span class="kc">False</span>
<span class="c1"># file main.py</span>
<span class="kn">import</span> <span class="nn">default_config</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">Options</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="n">timeout</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">one_flag</span><span class="p">:</span> <span class="nb">bool</span>
<span class="n">other_flag</span><span class="p">:</span> <span class="nb">bool</span>
<span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="n">options</span><span class="p">:</span> <span class="n">Options</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">setup</span><span class="p">(</span><span class="n">default_config</span><span class="p">)</span> <span class="c1"># OK</span>
</pre></div>
</div>
<p>To determine compatibility of module level functions, the <code class="docutils literal notranslate"><span class="pre">self</span></code> argument
of the corresponding protocol methods is dropped. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># callbacks.py</span>
<span class="k">def</span> <span class="nf">on_error</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">on_success</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="c1"># main.py</span>
<span class="kn">import</span> <span class="nn">callbacks</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">Reporter</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">on_error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">on_success</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">rp</span><span class="p">:</span> <span class="n">Reporter</span> <span class="o">=</span> <span class="n">callbacks</span> <span class="c1"># Passes type check</span>
</pre></div>
</div>
</section>
<section id="runtime-checkable-decorator-and-narrowing-types-by-isinstance">
<span id="discussion"></span><h3><a class="toc-backref" href="#runtime-checkable-decorator-and-narrowing-types-by-isinstance" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code> decorator and narrowing types by <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code></a></h3>
<p>The default semantics is that <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code> fail
for protocol types. This is in the spirit of duck typing protocols
basically would be used to model duck typing statically, not explicitly
at runtime.</p>
<p>However, it should be possible for protocol types to implement custom
instance and class checks when this makes sense, similar to how <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>
and other ABCs in <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> and <code class="docutils literal notranslate"><span class="pre">typing</span></code> already do it,
but this is limited to non-generic and unsubscripted generic protocols
(<code class="docutils literal notranslate"><span class="pre">Iterable</span></code> is statically equivalent to <code class="docutils literal notranslate"><span class="pre">Iterable[Any]</span></code>).
The <code class="docutils literal notranslate"><span class="pre">typing</span></code> module will define a special <code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code> class decorator
that provides the same semantics for class and instance checks as for
<code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> classes, essentially making them “runtime protocols”:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">runtime_checkable</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="nd">@runtime_checkable</span>
<span class="k">class</span> <span class="nc">SupportsClose</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s1">&#39;some/file&#39;</span><span class="p">),</span> <span class="n">SupportsClose</span><span class="p">)</span>
</pre></div>
</div>
<p>Note that instance checks are not 100% reliable statically, this is why
this behavior is opt-in, see section on <a class="reference internal" href="#pep-544-rejected">rejected</a>
ideas for examples.
The most type checkers can do is to treat <code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">Iterator)</span></code>
roughly as a simpler way to write
<code class="docutils literal notranslate"><span class="pre">hasattr(x,</span> <span class="pre">'__iter__')</span> <span class="pre">and</span> <span class="pre">hasattr(x,</span> <span class="pre">'__next__')</span></code>. To minimize
the risks for this feature, the following rules are applied.</p>
<p><strong>Definitions</strong>:</p>
<ul class="simple">
<li><em>Data, and non-data protocols</em>: A protocol is called non-data protocol
if it only contains methods as members (for example <code class="docutils literal notranslate"><span class="pre">Sized</span></code>,
<code class="docutils literal notranslate"><span class="pre">Iterator</span></code>, etc). A protocol that contains at least one non-method member
(like <code class="docutils literal notranslate"><span class="pre">x:</span> <span class="pre">int</span></code>) is called a data protocol.</li>
<li><em>Unsafe overlap</em>: A type <code class="docutils literal notranslate"><span class="pre">X</span></code> is called unsafely overlapping with
a protocol <code class="docutils literal notranslate"><span class="pre">P</span></code>, if <code class="docutils literal notranslate"><span class="pre">X</span></code> is not a subtype of <code class="docutils literal notranslate"><span class="pre">P</span></code>, but it is a subtype
of the type erased version of <code class="docutils literal notranslate"><span class="pre">P</span></code> where all members have type <code class="docutils literal notranslate"><span class="pre">Any</span></code>.
In addition, if at least one element of a union unsafely overlaps with
a protocol <code class="docutils literal notranslate"><span class="pre">P</span></code>, then the whole union is unsafely overlapping with <code class="docutils literal notranslate"><span class="pre">P</span></code>.</li>
</ul>
<p><strong>Specification</strong>:</p>
<ul class="simple">
<li>A protocol can be used as a second argument in <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and
<code class="docutils literal notranslate"><span class="pre">issubclass()</span></code> only if it is explicitly opt-in by <code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code>
decorator. This requirement exists because protocol checks are not type safe
in case of dynamically set attributes, and because type checkers can only prove
that an <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> check is safe only for a given class, not for all its
subclasses.</li>
<li><code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> can be used with both data and non-data protocols, while
<code class="docutils literal notranslate"><span class="pre">issubclass()</span></code> can be used only with non-data protocols. This restriction
exists because some data attributes can be set on an instance in constructor
and this information is not always available on the class object.</li>
<li>Type checkers should reject an <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> or <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code> call, if
there is an unsafe overlap between the type of the first argument and
the protocol.</li>
<li>Type checkers should be able to select a correct element from a union after
a safe <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> or <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code> call. For narrowing from non-union
types, type checkers can use their best judgement (this is intentionally
unspecified, since a precise specification would require intersection types).</li>
</ul>
</section>
</section>
<section id="using-protocols-in-python-2-7-3-5">
<h2><a class="toc-backref" href="#using-protocols-in-python-2-7-3-5" role="doc-backlink">Using Protocols in Python 2.7 - 3.5</a></h2>
<p>Variable annotation syntax was added in Python 3.6, so that the syntax
for defining protocol variables proposed in <a class="reference internal" href="#specification">specification</a> section cant
be used if support for earlier versions is needed. To define these
in a manner compatible with older versions of Python one can use properties.
Properties can be settable and/or abstract if needed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Foo</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">c</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">42</span> <span class="c1"># Default value can be provided for property...</span>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">d</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="c1"># ... or it can be abstract</span>
<span class="k">return</span> <span class="mi">0</span>
</pre></div>
</div>
<p>Also function type comments can be used as per <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> (for example
to provide compatibility with Python 2). The <code class="docutils literal notranslate"><span class="pre">typing</span></code> module changes
proposed in this PEP will also be backported to earlier versions via the
backport currently available on PyPI.</p>
</section>
<section id="runtime-implementation-of-protocol-classes">
<h2><a class="toc-backref" href="#runtime-implementation-of-protocol-classes" role="doc-backlink">Runtime Implementation of Protocol Classes</a></h2>
<section id="implementation-details">
<h3><a class="toc-backref" href="#implementation-details" role="doc-backlink">Implementation details</a></h3>
<p>The runtime implementation could be done in pure Python without any
effects on the core interpreter and standard library except in the
<code class="docutils literal notranslate"><span class="pre">typing</span></code> module, and a minor update to <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code>:</p>
<ul class="simple">
<li>Define class <code class="docutils literal notranslate"><span class="pre">typing.Protocol</span></code> similar to <code class="docutils literal notranslate"><span class="pre">typing.Generic</span></code>.</li>
<li>Implement functionality to detect whether a class is
a protocol or not. Add a class attribute <code class="docutils literal notranslate"><span class="pre">_is_protocol</span> <span class="pre">=</span> <span class="pre">True</span></code>
if that is the case. Verify that a protocol class only has protocol
base classes in the MRO (except for object).</li>
<li>Implement <code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code> that allows <code class="docutils literal notranslate"><span class="pre">__subclasshook__()</span></code>
performing structural instance and subclass checks as in <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code>
classes.</li>
<li>All structural subtyping checks will be performed by static type checkers,
such as <code class="docutils literal notranslate"><span class="pre">mypy</span></code> <a class="reference internal" href="#mypy" id="id9"><span>[mypy]</span></a>. No additional support for protocol validation will
be provided at runtime.</li>
</ul>
</section>
<section id="changes-in-the-typing-module">
<h3><a class="toc-backref" href="#changes-in-the-typing-module" role="doc-backlink">Changes in the typing module</a></h3>
<p>The following classes in <code class="docutils literal notranslate"><span class="pre">typing</span></code> module will be protocols:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">Callable</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Awaitable</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Iterable</span></code>, <code class="docutils literal notranslate"><span class="pre">Iterator</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">AsyncIterable</span></code>, <code class="docutils literal notranslate"><span class="pre">AsyncIterator</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Hashable</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Sized</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Container</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Collection</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Reversible</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">ContextManager</span></code>, <code class="docutils literal notranslate"><span class="pre">AsyncContextManager</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">SupportsAbs</span></code> (and other <code class="docutils literal notranslate"><span class="pre">Supports*</span></code> classes)</li>
</ul>
<p>Most of these classes are small and conceptually simple. It is easy to see
what are the methods these protocols implement, and immediately recognize
the corresponding runtime protocol counterpart.
Practically, few changes will be needed in <code class="docutils literal notranslate"><span class="pre">typing</span></code> since some of these
classes already behave the necessary way at runtime. Most of these will need
to be updated only in the corresponding <code class="docutils literal notranslate"><span class="pre">typeshed</span></code> stubs <a class="reference internal" href="#typeshed" id="id10"><span>[typeshed]</span></a>.</p>
<p>All other concrete generic classes such as <code class="docutils literal notranslate"><span class="pre">List</span></code>, <code class="docutils literal notranslate"><span class="pre">Set</span></code>, <code class="docutils literal notranslate"><span class="pre">IO</span></code>,
<code class="docutils literal notranslate"><span class="pre">Deque</span></code>, etc are sufficiently complex that it makes sense to keep
them non-protocols (i.e. require code to be explicit about them). Also, it is
too easy to leave some methods unimplemented by accident, and explicitly
marking the subclass relationship allows type checkers to pinpoint the missing
implementations.</p>
</section>
<section id="introspection">
<h3><a class="toc-backref" href="#introspection" role="doc-backlink">Introspection</a></h3>
<p>The existing class introspection machinery (<code class="docutils literal notranslate"><span class="pre">dir</span></code>, <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> etc)
can be used with protocols. In addition, all introspection tools implemented
in the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module will support protocols. Since all attributes need
to be defined in the class body based on this proposal, protocol classes will
have even better perspective for introspection than regular classes where
attributes can be defined implicitly protocol attributes cant be
initialized in ways that are not visible to introspection
(using <code class="docutils literal notranslate"><span class="pre">setattr()</span></code>, assignment via <code class="docutils literal notranslate"><span class="pre">self</span></code>, etc.). Still, some things like
types of attributes will not be visible at runtime in Python 3.5 and earlier,
but this looks like a reasonable limitation.</p>
<p>There will be only limited support of <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code>
as discussed above (these will <em>always</em> fail with <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> for
subscripted generic protocols, since a reliable answer could not be given
at runtime in this case). But together with other introspection tools this
give a reasonable perspective for runtime type checking tools.</p>
</section>
</section>
<section id="rejected-postponed-ideas">
<span id="pep-544-rejected"></span><h2><a class="toc-backref" href="#rejected-postponed-ideas" role="doc-backlink">Rejected/Postponed Ideas</a></h2>
<p>The ideas in this section were previously discussed in <a class="reference internal" href="#several" id="id11"><span>[several]</span></a>
<a class="reference internal" href="#discussions" id="id12"><span>[discussions]</span></a> <a class="reference internal" href="#elsewhere" id="id13"><span>[elsewhere]</span></a>.</p>
<section id="make-every-class-a-protocol-by-default">
<h3><a class="toc-backref" href="#make-every-class-a-protocol-by-default" role="doc-backlink">Make every class a protocol by default</a></h3>
<p>Some languages such as Go make structural subtyping the only or the primary
form of subtyping. We could achieve a similar result by making all classes
protocols by default (or even always). However we believe that it is better
to require classes to be explicitly marked as protocols, for the following
reasons:</p>
<ul class="simple">
<li>Protocols dont have some properties of regular classes. In particular,
<code class="docutils literal notranslate"><span class="pre">isinstance()</span></code>, as defined for normal classes, is based on the nominal
hierarchy. In order to make everything a protocol by default, and have
<code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> work would require changing its semantics,
which wont happen.</li>
<li>Protocol classes should generally not have many method implementations,
as they describe an interface, not an implementation.
Most classes have many method implementations, making them bad protocol
classes.</li>
<li>Experience suggests that many classes are not practical as protocols anyway,
mainly because their interfaces are too large, complex or
implementation-oriented (for example, they may include de facto
private attributes and methods without a <code class="docutils literal notranslate"><span class="pre">__</span></code> prefix).</li>
<li>Most actually useful protocols in existing Python code seem to be implicit.
The ABCs in <code class="docutils literal notranslate"><span class="pre">typing</span></code> and <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> are rather an exception, but
even they are recent additions to Python and most programmers
do not use them yet.</li>
<li>Many built-in functions only accept concrete instances of <code class="docutils literal notranslate"><span class="pre">int</span></code>
(and subclass instances), and similarly for other built-in classes. Making
<code class="docutils literal notranslate"><span class="pre">int</span></code> a structural type wouldnt be safe without major changes to the
Python runtime, which wont happen.</li>
</ul>
</section>
<section id="protocols-subclassing-normal-classes">
<h3><a class="toc-backref" href="#protocols-subclassing-normal-classes" role="doc-backlink">Protocols subclassing normal classes</a></h3>
<p>The main rationale to prohibit this is to preserve transitivity of subtyping,
consider this example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Protocol</span>
<span class="k">class</span> <span class="nc">Base</span><span class="p">:</span>
<span class="n">attr</span><span class="p">:</span> <span class="nb">str</span>
<span class="k">class</span> <span class="nc">Proto</span><span class="p">(</span><span class="n">Base</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">attr</span><span class="p">:</span> <span class="nb">str</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
</pre></div>
</div>
<p>Now, <code class="docutils literal notranslate"><span class="pre">C</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Proto</span></code>, and <code class="docutils literal notranslate"><span class="pre">Proto</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Base</span></code>.
But <code class="docutils literal notranslate"><span class="pre">C</span></code> cannot be a subtype of <code class="docutils literal notranslate"><span class="pre">Base</span></code> (since the latter is not
a protocol). This situation would be really weird. In addition, there is
an ambiguity about whether attributes of <code class="docutils literal notranslate"><span class="pre">Base</span></code> should become protocol
members of <code class="docutils literal notranslate"><span class="pre">Proto</span></code>.</p>
</section>
<section id="support-optional-protocol-members">
<h3><a class="toc-backref" href="#support-optional-protocol-members" role="doc-backlink">Support optional protocol members</a></h3>
<p>We can come up with examples where it would be handy to be able to say
that a method or data attribute does not need to be present in a class
implementing a protocol, but if it is present, it must conform to a specific
signature or type. One could use a <code class="docutils literal notranslate"><span class="pre">hasattr()</span></code> check to determine whether
they can use the attribute on a particular instance.</p>
<p>Languages such as TypeScript have similar features and
apparently they are pretty commonly used. The current realistic potential
use cases for protocols in Python dont require these. In the interest
of simplicity, we propose to not support optional methods or attributes.
We can always revisit this later if there is an actual need.</p>
</section>
<section id="allow-only-protocol-methods-and-force-use-of-getters-and-setters">
<h3><a class="toc-backref" href="#allow-only-protocol-methods-and-force-use-of-getters-and-setters" role="doc-backlink">Allow only protocol methods and force use of getters and setters</a></h3>
<p>One could argue that protocols typically only define methods, but not
variables. However, using getters and setters in cases where only a
simple variable is needed would be quite unpythonic. Moreover, the widespread
use of properties (that often act as type validators) in large code bases
is partially due to previous absence of static type checkers for Python,
the problem that <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> and this PEP are aiming to solve. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># without static types</span>
<span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">my_attr</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_my_attr</span>
<span class="nd">@my_attr</span><span class="o">.</span><span class="n">setter</span>
<span class="k">def</span> <span class="nf">my_attr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
<span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="s2">&quot;An integer expected for my_attr&quot;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_my_attr</span> <span class="o">=</span> <span class="n">value</span>
<span class="c1"># with static types</span>
<span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span>
<span class="n">my_attr</span><span class="p">:</span> <span class="nb">int</span>
</pre></div>
</div>
</section>
<section id="support-non-protocol-members">
<h3><a class="toc-backref" href="#support-non-protocol-members" role="doc-backlink">Support non-protocol members</a></h3>
<p>There was an idea to make some methods “non-protocol” (i.e. not necessary
to implement, and inherited in explicit subclassing), but it was rejected,
since this complicates things. For example, consider this situation:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Proto</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
<span class="k">def</span> <span class="nf">second</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">first</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">fun</span><span class="p">(</span><span class="n">arg</span><span class="p">:</span> <span class="n">Proto</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">arg</span><span class="o">.</span><span class="n">second</span><span class="p">()</span>
</pre></div>
</div>
<p>The question is should this be an error? We think most people would expect
this to be valid. Therefore, to be on the safe side, we need to require both
methods to be implemented in implicit subclasses. In addition, if one looks
at definitions in <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code>, there are very few methods that could
be considered “non-protocol”. Therefore, it was decided to not introduce
“non-protocol” methods.</p>
<p>There is only one downside to this: it will require some boilerplate for
implicit subtypes of “large” protocols. But, this doesnt apply to “built-in”
protocols that are all “small” (i.e. have only few abstract methods).
Also, such style is discouraged for user-defined protocols. It is recommended
to create compact protocols and combine them.</p>
</section>
<section id="make-protocols-interoperable-with-other-approaches">
<h3><a class="toc-backref" href="#make-protocols-interoperable-with-other-approaches" role="doc-backlink">Make protocols interoperable with other approaches</a></h3>
<p>The protocols as described here are basically a minimal extension to
the existing concept of ABCs. We argue that this is the way they should
be understood, instead of as something that <em>replaces</em> Zope interfaces,
for example. Attempting such interoperabilities will significantly
complicate both the concept and the implementation.</p>
<p>On the other hand, Zope interfaces are conceptually a superset of protocols
defined here, but using an incompatible syntax to define them,
because before <a class="pep reference internal" href="../pep-0526/" title="PEP 526 Syntax for Variable Annotations">PEP 526</a> there was no straightforward way to annotate attributes.
In the 3.6+ world, <code class="docutils literal notranslate"><span class="pre">zope.interface</span></code> might potentially adopt the <code class="docutils literal notranslate"><span class="pre">Protocol</span></code>
syntax. In this case, type checkers could be taught to recognize interfaces
as protocols and make simple structural checks with respect to them.</p>
</section>
<section id="use-assignments-to-check-explicitly-that-a-class-implements-a-protocol">
<h3><a class="toc-backref" href="#use-assignments-to-check-explicitly-that-a-class-implements-a-protocol" role="doc-backlink">Use assignments to check explicitly that a class implements a protocol</a></h3>
<p>In the Go language the explicit checks for implementation are performed
via dummy assignments <a class="reference internal" href="#golang" id="id14"><span>[golang]</span></a>. Such a way is also possible with the
current proposal. Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">float</span><span class="p">:</span>
<span class="k">return</span> <span class="o">...</span>
<span class="n">_</span><span class="p">:</span> <span class="n">Sized</span> <span class="o">=</span> <span class="n">A</span><span class="p">()</span> <span class="c1"># Error: A.__len__ doesn&#39;t conform to &#39;Sized&#39;</span>
<span class="c1"># (Incompatible return type &#39;float&#39;)</span>
</pre></div>
</div>
<p>This approach moves the check away from
the class definition and it almost requires a comment as otherwise
the code probably would not make any sense to an average reader
it looks like dead code. Besides, in the simplest form it requires one
to construct an instance of <code class="docutils literal notranslate"><span class="pre">A</span></code>, which could be problematic if this requires
accessing or allocating some resources such as files or sockets.
We could work around the latter by using a cast, for example, but then
the code would be ugly. Therefore, we discourage the use of this pattern.</p>
</section>
<section id="support-isinstance-checks-by-default">
<h3><a class="toc-backref" href="#support-isinstance-checks-by-default" role="doc-backlink">Support <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> checks by default</a></h3>
<p>The problem with this is instance checks could be unreliable, except for
situations where there is a common signature convention such as <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>.
For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">P</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">common_method_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="k">class</span> <span class="nc">X</span><span class="p">:</span>
<span class="o">&lt;</span><span class="n">a</span> <span class="n">bunch</span> <span class="n">of</span> <span class="n">methods</span><span class="o">&gt;</span>
<span class="k">def</span> <span class="nf">common_method_name</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># Note different signature</span>
<span class="k">def</span> <span class="nf">do_stuff</span><span class="p">(</span><span class="n">o</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="n">X</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">P</span><span class="p">):</span>
<span class="k">return</span> <span class="n">o</span><span class="o">.</span><span class="n">common_method_name</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># Results in TypeError not caught</span>
<span class="c1"># statically if o is an X instance.</span>
</pre></div>
</div>
<p>Another potentially problematic case is assignment of attributes
<em>after</em> instantiation:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">P</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="nb">isinstance</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span> <span class="c1"># False</span>
<span class="n">c</span><span class="o">.</span><span class="n">initialize</span><span class="p">()</span>
<span class="nb">isinstance</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span> <span class="c1"># True</span>
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">P</span><span class="p">):</span>
<span class="c1"># Static type of x is P here.</span>
<span class="o">...</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Static type of x is int, but can be other type at runtime...</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">f</span><span class="p">(</span><span class="n">C</span><span class="p">())</span> <span class="c1"># ...causing a TypeError.</span>
</pre></div>
</div>
<p>We argue that requiring an explicit class decorator would be better, since
one can then attach warnings about problems like this in the documentation.
The user would be able to evaluate whether the benefits outweigh
the potential for confusion for each protocol and explicitly opt in but
the default behavior would be safer. Finally, it will be easy to make this
behavior default if necessary, while it might be problematic to make it opt-in
after being default.</p>
</section>
<section id="provide-a-special-intersection-type-construct">
<h3><a class="toc-backref" href="#provide-a-special-intersection-type-construct" role="doc-backlink">Provide a special intersection type construct</a></h3>
<p>There was an idea to allow <code class="docutils literal notranslate"><span class="pre">Proto</span> <span class="pre">=</span> <span class="pre">All[Proto1,</span> <span class="pre">Proto2,</span> <span class="pre">...]</span></code> as a shorthand
for:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Proto</span><span class="p">(</span><span class="n">Proto1</span><span class="p">,</span> <span class="n">Proto2</span><span class="p">,</span> <span class="o">...</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>However, it is not yet clear how popular/useful it will be and implementing
this in type checkers for non-protocol classes could be difficult. Finally, it
will be very easy to add this later if needed.</p>
</section>
<section id="prohibit-explicit-subclassing-of-protocols-by-non-protocols">
<h3><a class="toc-backref" href="#prohibit-explicit-subclassing-of-protocols-by-non-protocols" role="doc-backlink">Prohibit explicit subclassing of protocols by non-protocols</a></h3>
<p>This was rejected for the following reasons:</p>
<ul class="simple">
<li>Backward compatibility: People are already using ABCs, including generic
ABCs from <code class="docutils literal notranslate"><span class="pre">typing</span></code> module. If we prohibit explicit subclassing of these
ABCs, then quite a lot of code will break.</li>
<li>Convenience: There are existing protocol-like ABCs (that may be turned
into protocols) that have many useful “mix-in” (non-abstract) methods.
For example, in the case of <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> one only needs to implement
<code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> and <code class="docutils literal notranslate"><span class="pre">__len__</span></code> in an explicit subclass, and one gets
<code class="docutils literal notranslate"><span class="pre">__iter__</span></code>, <code class="docutils literal notranslate"><span class="pre">__contains__</span></code>, <code class="docutils literal notranslate"><span class="pre">__reversed__</span></code>, <code class="docutils literal notranslate"><span class="pre">index</span></code>, and <code class="docutils literal notranslate"><span class="pre">count</span></code>
for free.</li>
<li>Explicit subclassing makes it explicit that a class implements a particular
protocol, making subtyping relationships easier to see.</li>
<li>Type checkers can warn about missing protocol members or members with
incompatible types more easily, without having to use hacks like dummy
assignments discussed above in this section.</li>
<li>Explicit subclassing makes it possible to force a class to be considered
a subtype of a protocol (by using <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> together with an
explicit base class) when it is not strictly compatible, such as when
it has an unsafe override.</li>
</ul>
</section>
<section id="covariant-subtyping-of-mutable-attributes">
<h3><a class="toc-backref" href="#covariant-subtyping-of-mutable-attributes" role="doc-backlink">Covariant subtyping of mutable attributes</a></h3>
<p>Rejected because covariant subtyping of mutable attributes is not safe.
Consider this example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">P</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">float</span>
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">arg</span><span class="p">:</span> <span class="n">P</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">arg</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mf">0.42</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">f</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="c1"># Would typecheck if covariant subtyping</span>
<span class="c1"># of mutable attributes were allowed.</span>
<span class="n">c</span><span class="o">.</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="c1"># But this fails at runtime</span>
</pre></div>
</div>
<p>It was initially proposed to allow this for practical reasons, but it was
subsequently rejected, since this may mask some hard to spot bugs.</p>
</section>
<section id="overriding-inferred-variance-of-protocol-classes">
<h3><a class="toc-backref" href="#overriding-inferred-variance-of-protocol-classes" role="doc-backlink">Overriding inferred variance of protocol classes</a></h3>
<p>It was proposed to allow declaring protocols as invariant if they are actually
covariant or contravariant (as it is possible for nominal classes, see <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a>).
However, it was decided not to do this because of several downsides:</p>
<ul>
<li>Declared protocol invariance breaks transitivity of sub-typing. Consider
this situation:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">&#39;T&#39;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">P</span><span class="p">(</span><span class="n">Protocol</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span> <span class="c1"># Protocol is declared as invariant.</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">float</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">D</span><span class="p">(</span><span class="n">C</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Now we have that <code class="docutils literal notranslate"><span class="pre">D</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">C</span></code>, and <code class="docutils literal notranslate"><span class="pre">C</span></code> is a subtype of
<code class="docutils literal notranslate"><span class="pre">P[float]</span></code>. But <code class="docutils literal notranslate"><span class="pre">D</span></code> is <em>not</em> a subtype of <code class="docutils literal notranslate"><span class="pre">P[float]</span></code> since <code class="docutils literal notranslate"><span class="pre">D</span></code>
implements <code class="docutils literal notranslate"><span class="pre">P[int]</span></code>, and <code class="docutils literal notranslate"><span class="pre">P</span></code> is invariant. There is a possibility
to “cure” this by looking for protocol implementations in MROs but this
will be too complex in a general case, and this “cure” requires abandoning
simple idea of purely structural subtyping for protocols.</p>
</li>
<li>Subtyping checks will always require type inference for protocols. In the
above example a user may complain: “Why did you infer <code class="docutils literal notranslate"><span class="pre">P[int]</span></code> for
my <code class="docutils literal notranslate"><span class="pre">D</span></code>? It implements <code class="docutils literal notranslate"><span class="pre">P[float]</span></code>!”. Normally, inference can be overruled
by an explicit annotation, but here this will require explicit subclassing,
defeating the purpose of using protocols.</li>
<li>Allowing overriding variance will make impossible more detailed error
messages in type checkers citing particular conflicts in member
type signatures.</li>
<li>Finally, explicit is better than implicit in this case. Requiring user to
declare correct variance will simplify understanding the code and will avoid
unexpected errors at the point of use.</li>
</ul>
</section>
<section id="support-adapters-and-adaptation">
<h3><a class="toc-backref" href="#support-adapters-and-adaptation" role="doc-backlink">Support adapters and adaptation</a></h3>
<p>Adaptation was proposed by <a class="pep reference internal" href="../pep-0246/" title="PEP 246 Object Adaptation">PEP 246</a> (rejected) and is supported by
<code class="docutils literal notranslate"><span class="pre">zope.interface</span></code>, see <a class="reference external" href="https://web.archive.org/web/20160802080957/https://docs.zope.org/zope.interface/adapter.html">the Zope documentation on adapter registries</a>.
Adapters is quite an advanced concept, and <a class="pep reference internal" href="../pep-0484/" title="PEP 484 Type Hints">PEP 484</a> supports unions and
generic aliases that can be used instead of adapters. This can be illustrated
with an example of <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> protocol, there is another way of supporting
iteration by providing <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> and <code class="docutils literal notranslate"><span class="pre">__len__</span></code>. If a function
supports both this way and the now standard <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method, then it could
be annotated by a union type:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">OldIterable</span><span class="p">(</span><span class="n">Sized</span><span class="p">,</span> <span class="n">Protocol</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span> <span class="o">...</span>
<span class="n">CompatIterable</span> <span class="o">=</span> <span class="n">Union</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="n">T</span><span class="p">],</span> <span class="n">OldIterable</span><span class="p">[</span><span class="n">T</span><span class="p">]]</span>
<span class="k">class</span> <span class="nc">A</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Iterator</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span> <span class="o">...</span>
<span class="k">class</span> <span class="nc">B</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span> <span class="o">...</span>
<span class="k">def</span> <span class="nf">iterate</span><span class="p">(</span><span class="n">it</span><span class="p">:</span> <span class="n">CompatIterable</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="o">...</span>
<span class="n">iterate</span><span class="p">(</span><span class="n">A</span><span class="p">())</span> <span class="c1"># OK</span>
<span class="n">iterate</span><span class="p">(</span><span class="n">B</span><span class="p">())</span> <span class="c1"># OK</span>
</pre></div>
</div>
<p>Since there is a reasonable alternative for such cases with existing tooling,
it is therefore proposed not to include adaptation in this PEP.</p>
</section>
<section id="call-structural-base-types-interfaces">
<h3><a class="toc-backref" href="#call-structural-base-types-interfaces" role="doc-backlink">Call structural base types “interfaces”</a></h3>
<p>“Protocol” is a term already widely used in Python to describe duck typing
contracts such as the iterator protocol (providing <code class="docutils literal notranslate"><span class="pre">__iter__</span></code>
and <code class="docutils literal notranslate"><span class="pre">__next__</span></code>), and the descriptor protocol (providing <code class="docutils literal notranslate"><span class="pre">__get__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__set__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__delete__</span></code>). In addition to this and other reasons given
in <a class="reference internal" href="#specification">specification</a>, protocols are different from Java interfaces in several
aspects: protocols dont require explicit declaration of implementation
(they are mainly oriented on duck-typing), protocols can have
default implementations of members and store state.</p>
</section>
<section id="make-protocols-special-objects-at-runtime-rather-than-normal-abcs">
<h3><a class="toc-backref" href="#make-protocols-special-objects-at-runtime-rather-than-normal-abcs" role="doc-backlink">Make protocols special objects at runtime rather than normal ABCs</a></h3>
<p>Making protocols non-ABCs will make the backwards compatibility problematic
if possible at all. For example, <code class="docutils literal notranslate"><span class="pre">collections.abc.Iterable</span></code> is already
an ABC, and lots of existing code use patterns like
<code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">collections.abc.Iterable)</span></code> and similar checks with other
ABCs (also in a structural manner, i.e., via <code class="docutils literal notranslate"><span class="pre">__subclasshook__</span></code>).
Disabling this behavior will cause breakages. If we keep this behavior
for ABCs in <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> but will not provide a similar runtime
behavior for protocols in <code class="docutils literal notranslate"><span class="pre">typing</span></code>, then a smooth transition to protocols
will be not possible. In addition, having two parallel hierarchies may cause
confusions.</p>
</section>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
<p>This PEP is fully backwards compatible.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">mypy</span></code> type checker fully supports protocols (modulo a few
known bugs). This includes treating all the builtin protocols, such as
<code class="docutils literal notranslate"><span class="pre">Iterable</span></code> structurally. The runtime implementation of protocols is
available in <code class="docutils literal notranslate"><span class="pre">typing_extensions</span></code> module on PyPI.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<div role="list" class="citation-list">
<div class="citation" id="typing" role="doc-biblioentry">
<dt class="label" id="typing">[<a href="#id1">typing</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/library/typing.html">https://docs.python.org/3/library/typing.html</a></div>
<div class="citation" id="wiki-structural" role="doc-biblioentry">
<dt class="label" id="wiki-structural">[<a href="#id2">wiki-structural</a>]</dt>
<dd><a class="reference external" href="https://en.wikipedia.org/wiki/Structural_type_system">https://en.wikipedia.org/wiki/Structural_type_system</a></div>
<div class="citation" id="zope-interfaces" role="doc-biblioentry">
<dt class="label" id="zope-interfaces">[<a href="#id3">zope-interfaces</a>]</dt>
<dd><a class="reference external" href="https://zopeinterface.readthedocs.io/en/latest/">https://zopeinterface.readthedocs.io/en/latest/</a></div>
<div class="citation" id="abstract-classes" role="doc-biblioentry">
<dt class="label" id="abstract-classes">[<a href="#id4">abstract-classes</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/library/abc.html">https://docs.python.org/3/library/abc.html</a></div>
<div class="citation" id="collections-abc" role="doc-biblioentry">
<dt class="label" id="collections-abc">[<a href="#id5">collections-abc</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/library/collections.abc.html">https://docs.python.org/3/library/collections.abc.html</a></div>
<div class="citation" id="typescript" role="doc-biblioentry">
<dt class="label" id="typescript">[<a href="#id6">typescript</a>]</dt>
<dd><a class="reference external" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">https://www.typescriptlang.org/docs/handbook/interfaces.html</a></div>
<div class="citation" id="golang" role="doc-biblioentry">
<dt class="label" id="golang">[golang]<em> (<a href='#id7'>1</a>, <a href='#id14'>2</a>) </em></dt>
<dd><a class="reference external" href="https://golang.org/doc/effective_go.html#interfaces_and_types">https://golang.org/doc/effective_go.html#interfaces_and_types</a></div>
<div class="citation" id="data-model" role="doc-biblioentry">
<dt class="label" id="data-model">[<a href="#id8">data-model</a>]</dt>
<dd><a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#special-method-names">https://docs.python.org/3/reference/datamodel.html#special-method-names</a></div>
<div class="citation" id="typeshed" role="doc-biblioentry">
<dt class="label" id="typeshed">[<a href="#id10">typeshed</a>]</dt>
<dd><a class="reference external" href="https://github.com/python/typeshed/">https://github.com/python/typeshed/</a></div>
<div class="citation" id="mypy" role="doc-biblioentry">
<dt class="label" id="mypy">[<a href="#id9">mypy</a>]</dt>
<dd><a class="reference external" href="http://github.com/python/mypy/">http://github.com/python/mypy/</a></div>
<div class="citation" id="several" role="doc-biblioentry">
<dt class="label" id="several">[<a href="#id11">several</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2015-September/thread.html#35859">https://mail.python.org/pipermail/python-ideas/2015-September/thread.html#35859</a></div>
<div class="citation" id="discussions" role="doc-biblioentry">
<dt class="label" id="discussions">[<a href="#id12">discussions</a>]</dt>
<dd><a class="reference external" href="https://github.com/python/typing/issues/11">https://github.com/python/typing/issues/11</a></div>
<div class="citation" id="elsewhere" role="doc-biblioentry">
<dt class="label" id="elsewhere">[<a href="#id13">elsewhere</a>]</dt>
<dd><a class="reference external" href="https://github.com/python/peps/pull/224">https://github.com/python/peps/pull/224</a></div>
</div>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0544.rst">https://github.com/python/peps/blob/main/peps/pep-0544.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0544.rst">2024-06-11 22:12:09 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a><ul>
<li><a class="reference internal" href="#nominal-vs-structural-subtyping">Nominal vs structural subtyping</a></li>
<li><a class="reference internal" href="#non-goals">Non-goals</a></li>
</ul>
</li>
<li><a class="reference internal" href="#existing-approaches-to-structural-subtyping">Existing Approaches to Structural Subtyping</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#terminology">Terminology</a></li>
<li><a class="reference internal" href="#defining-a-protocol">Defining a protocol</a></li>
<li><a class="reference internal" href="#protocol-members">Protocol members</a></li>
<li><a class="reference internal" href="#explicitly-declaring-implementation">Explicitly declaring implementation</a></li>
<li><a class="reference internal" href="#merging-and-extending-protocols">Merging and extending protocols</a></li>
<li><a class="reference internal" href="#generic-protocols">Generic protocols</a></li>
<li><a class="reference internal" href="#recursive-protocols">Recursive protocols</a></li>
<li><a class="reference internal" href="#self-types-in-protocols">Self-types in protocols</a></li>
<li><a class="reference internal" href="#callback-protocols">Callback protocols</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-protocols">Using Protocols</a><ul>
<li><a class="reference internal" href="#subtyping-relationships-with-other-types">Subtyping relationships with other types</a></li>
<li><a class="reference internal" href="#unions-and-intersections-of-protocols">Unions and intersections of protocols</a></li>
<li><a class="reference internal" href="#type-and-class-objects-vs-protocols"><code class="docutils literal notranslate"><span class="pre">Type[]</span></code> and class objects vs protocols</a></li>
<li><a class="reference internal" href="#newtype-and-type-aliases"><code class="docutils literal notranslate"><span class="pre">NewType()</span></code> and type aliases</a></li>
<li><a class="reference internal" href="#modules-as-implementations-of-protocols">Modules as implementations of protocols</a></li>
<li><a class="reference internal" href="#runtime-checkable-decorator-and-narrowing-types-by-isinstance"><code class="docutils literal notranslate"><span class="pre">&#64;runtime_checkable</span></code> decorator and narrowing types by <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-protocols-in-python-2-7-3-5">Using Protocols in Python 2.7 - 3.5</a></li>
<li><a class="reference internal" href="#runtime-implementation-of-protocol-classes">Runtime Implementation of Protocol Classes</a><ul>
<li><a class="reference internal" href="#implementation-details">Implementation details</a></li>
<li><a class="reference internal" href="#changes-in-the-typing-module">Changes in the typing module</a></li>
<li><a class="reference internal" href="#introspection">Introspection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rejected-postponed-ideas">Rejected/Postponed Ideas</a><ul>
<li><a class="reference internal" href="#make-every-class-a-protocol-by-default">Make every class a protocol by default</a></li>
<li><a class="reference internal" href="#protocols-subclassing-normal-classes">Protocols subclassing normal classes</a></li>
<li><a class="reference internal" href="#support-optional-protocol-members">Support optional protocol members</a></li>
<li><a class="reference internal" href="#allow-only-protocol-methods-and-force-use-of-getters-and-setters">Allow only protocol methods and force use of getters and setters</a></li>
<li><a class="reference internal" href="#support-non-protocol-members">Support non-protocol members</a></li>
<li><a class="reference internal" href="#make-protocols-interoperable-with-other-approaches">Make protocols interoperable with other approaches</a></li>
<li><a class="reference internal" href="#use-assignments-to-check-explicitly-that-a-class-implements-a-protocol">Use assignments to check explicitly that a class implements a protocol</a></li>
<li><a class="reference internal" href="#support-isinstance-checks-by-default">Support <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> checks by default</a></li>
<li><a class="reference internal" href="#provide-a-special-intersection-type-construct">Provide a special intersection type construct</a></li>
<li><a class="reference internal" href="#prohibit-explicit-subclassing-of-protocols-by-non-protocols">Prohibit explicit subclassing of protocols by non-protocols</a></li>
<li><a class="reference internal" href="#covariant-subtyping-of-mutable-attributes">Covariant subtyping of mutable attributes</a></li>
<li><a class="reference internal" href="#overriding-inferred-variance-of-protocol-classes">Overriding inferred variance of protocol classes</a></li>
<li><a class="reference internal" href="#support-adapters-and-adaptation">Support adapters and adaptation</a></li>
<li><a class="reference internal" href="#call-structural-base-types-interfaces">Call structural base types “interfaces”</a></li>
<li><a class="reference internal" href="#make-protocols-special-objects-at-runtime-rather-than-normal-abcs">Make protocols special objects at runtime rather than normal ABCs</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0544.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>