CINXE.COM
PEP 483 – The Theory of Type Hints | peps.python.org
<!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 483 – The Theory of Type Hints | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0483/"> <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 483 – The Theory of Type Hints | peps.python.org'> <meta property="og:description" content="This PEP lays out the theory referenced by PEP 484."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0483/"> <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="This PEP lays out the theory referenced by PEP 484."> <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> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 483</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 483 – The Theory of Type Hints</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Guido van Rossum <guido at python.org>, Ivan Levkivskyi <levkivskyi at gmail.com></dd> <dt class="field-even">Discussions-To<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/python-ideas@python.org/">Python-Ideas list</a></dd> <dt class="field-odd">Status<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-even">Type<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd> <dt class="field-odd">Topic<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="../topic/typing/">Typing</a></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">19-Dec-2014</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd"><p></p></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="#introduction">Introduction</a><ul> <li><a class="reference internal" href="#notational-conventions">Notational conventions</a></li> </ul> </li> <li><a class="reference internal" href="#background">Background</a><ul> <li><a class="reference internal" href="#subtype-relationships">Subtype relationships</a></li> </ul> </li> <li><a class="reference internal" href="#summary-of-gradual-typing">Summary of gradual typing</a><ul> <li><a class="reference internal" href="#types-vs-classes">Types vs. Classes</a></li> <li><a class="reference internal" href="#fundamental-building-blocks">Fundamental building blocks</a></li> </ul> </li> <li><a class="reference internal" href="#generic-types">Generic types</a><ul> <li><a class="reference internal" href="#type-variables">Type variables</a></li> <li><a class="reference internal" href="#defining-and-using-generic-types">Defining and using generic types</a></li> <li><a class="reference internal" href="#covariance-and-contravariance">Covariance and Contravariance</a></li> </ul> </li> <li><a class="reference internal" href="#pragmatics">Pragmatics</a><ul> <li><a class="reference internal" href="#predefined-generic-types-and-protocols-in-typing-py">Predefined generic types and Protocols in typing.py</a></li> </ul> </li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP lays out the theory referenced by <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>.</p> </section> <section id="introduction"> <h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2> <p>This document lays out the theory of the new type hinting proposal for Python 3.5. It’s not quite a full proposal or specification because there are many details that need to be worked out, but it lays out the theory without which it is hard to discuss more detailed specifications. We start by recalling basic concepts of type theory; then we explain gradual typing; then we state some general rules and define the new special types (such as <code class="docutils literal notranslate"><span class="pre">Union</span></code>) that can be used in annotations; and finally we define the approach to generic types and pragmatic aspects of type hinting.</p> <section id="notational-conventions"> <h3><a class="toc-backref" href="#notational-conventions" role="doc-backlink">Notational conventions</a></h3> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">t1</span></code>, <code class="docutils literal notranslate"><span class="pre">t2</span></code>, etc. and <code class="docutils literal notranslate"><span class="pre">u1</span></code>, <code class="docutils literal notranslate"><span class="pre">u2</span></code>, etc. are types. Sometimes we write <code class="docutils literal notranslate"><span class="pre">ti</span></code> or <code class="docutils literal notranslate"><span class="pre">tj</span></code> to refer to “any of <code class="docutils literal notranslate"><span class="pre">t1</span></code>, <code class="docutils literal notranslate"><span class="pre">t2</span></code>, etc.”</li> <li><code class="docutils literal notranslate"><span class="pre">T</span></code>, <code class="docutils literal notranslate"><span class="pre">U</span></code> etc. are type variables (defined with <code class="docutils literal notranslate"><span class="pre">TypeVar()</span></code>, see below).</li> <li>Objects, classes defined with a class statement, and instances are denoted using standard <a class="pep reference internal" href="../pep-0008/" title="PEP 8 – Style Guide for Python Code">PEP 8</a> conventions.</li> <li>the symbol <code class="docutils literal notranslate"><span class="pre">==</span></code> applied to types in the context of this PEP means that two expressions represent the same type.</li> <li>Note that <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> makes a distinction between types and classes (a type is a concept for the type checker, while a class is a runtime concept). In this PEP we clarify this distinction but avoid unnecessary strictness to allow more flexibility in the implementation of type checkers.</li> </ul> </section> </section> <section id="background"> <h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2> <p>There are many definitions of the concept of type in the literature. Here we assume that type is a set of values and a set of functions that one can apply to these values.</p> <p>There are several ways to define a particular type:</p> <ul> <li>By explicitly listing all values. E.g., <code class="docutils literal notranslate"><span class="pre">True</span></code> and <code class="docutils literal notranslate"><span class="pre">False</span></code> form the type <code class="docutils literal notranslate"><span class="pre">bool</span></code>.</li> <li>By specifying functions which can be used with variables of a type. E.g. all objects that have a <code class="docutils literal notranslate"><span class="pre">__len__</span></code> method form the type <code class="docutils literal notranslate"><span class="pre">Sized</span></code>. Both <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> and <code class="docutils literal notranslate"><span class="pre">'abc'</span></code> belong to this type, since one can call <code class="docutils literal notranslate"><span class="pre">len</span></code> on them:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">len</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</span> <span class="nb">len</span><span class="p">(</span><span class="s1">'abc'</span><span class="p">)</span> <span class="c1"># also OK</span> <span class="nb">len</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># not a member of Sized</span> </pre></div> </div> </li> <li>By a simple class definition, for example if one defines a class:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">UserID</span><span class="p">(</span><span class="nb">int</span><span class="p">):</span> <span class="k">pass</span> </pre></div> </div> <p>then all instances of this class also form a type.</p> </li> <li>There are also more complex types. E.g., one can define the type <code class="docutils literal notranslate"><span class="pre">FancyList</span></code> as all lists containing only instances of <code class="docutils literal notranslate"><span class="pre">int</span></code>, <code class="docutils literal notranslate"><span class="pre">str</span></code> or their subclasses. The value <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">'abc',</span> <span class="pre">UserID(42)]</span></code> has this type.</li> </ul> <p>It is important for the user to be able to define types in a form that can be understood by type checkers. The goal of this PEP is to propose such a systematic way of defining types for type annotations of variables and functions using <a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a> syntax. These annotations can be used to avoid many kind of bugs, for documentation purposes, or maybe even to increase speed of program execution. Here we only focus on avoiding bugs by using a static type checker.</p> <section id="subtype-relationships"> <h3><a class="toc-backref" href="#subtype-relationships" role="doc-backlink">Subtype relationships</a></h3> <p>A crucial notion for static type checker is the subtype relationship. It arises from the question: If <code class="docutils literal notranslate"><span class="pre">first_var</span></code> has type <code class="docutils literal notranslate"><span class="pre">first_type</span></code>, and <code class="docutils literal notranslate"><span class="pre">second_var</span></code> has type <code class="docutils literal notranslate"><span class="pre">second_type</span></code>, is it safe to assign <code class="docutils literal notranslate"><span class="pre">first_var</span> <span class="pre">=</span> <span class="pre">second_var</span></code>?</p> <p>A strong criterion for when it <em>should</em> be safe is:</p> <ul class="simple"> <li>every value from <code class="docutils literal notranslate"><span class="pre">second_type</span></code> is also in the set of values of <code class="docutils literal notranslate"><span class="pre">first_type</span></code>; and</li> <li>every function from <code class="docutils literal notranslate"><span class="pre">first_type</span></code> is also in the set of functions of <code class="docutils literal notranslate"><span class="pre">second_type</span></code>.</li> </ul> <p>The relation defined thus is called a subtype relation.</p> <p>By this definition:</p> <ul class="simple"> <li>Every type is a subtype of itself.</li> <li>The set of values becomes smaller in the process of subtyping, while the set of functions becomes larger.</li> </ul> <p>An intuitive example: Every <code class="docutils literal notranslate"><span class="pre">Dog</span></code> is an <code class="docutils literal notranslate"><span class="pre">Animal</span></code>, also <code class="docutils literal notranslate"><span class="pre">Dog</span></code> has more functions, for example it can bark, therefore <code class="docutils literal notranslate"><span class="pre">Dog</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Animal</span></code>. Conversely, <code class="docutils literal notranslate"><span class="pre">Animal</span></code> is not a subtype of <code class="docutils literal notranslate"><span class="pre">Dog</span></code>.</p> <p>A more formal example: Integers are subtype of real numbers. Indeed, every integer is of course also a real number, and integers support more operations, such as, e.g., bitwise shifts <code class="docutils literal notranslate"><span class="pre"><<</span></code> and <code class="docutils literal notranslate"><span class="pre">>></span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">lucky_number</span> <span class="o">=</span> <span class="mf">3.14</span> <span class="c1"># type: float</span> <span class="n">lucky_number</span> <span class="o">=</span> <span class="mi">42</span> <span class="c1"># Safe</span> <span class="n">lucky_number</span> <span class="o">*</span> <span class="mi">2</span> <span class="c1"># This works</span> <span class="n">lucky_number</span> <span class="o"><<</span> <span class="mi">5</span> <span class="c1"># Fails</span> <span class="n">unlucky_number</span> <span class="o">=</span> <span class="mi">13</span> <span class="c1"># type: int</span> <span class="n">unlucky_number</span> <span class="o"><<</span> <span class="mi">5</span> <span class="c1"># This works</span> <span class="n">unlucky_number</span> <span class="o">=</span> <span class="mf">2.72</span> <span class="c1"># Unsafe</span> </pre></div> </div> <p>Let us also consider a tricky example: If <code class="docutils literal notranslate"><span class="pre">List[int]</span></code> denotes the type formed by all lists containing only integer numbers, then it is <em>not</em> a subtype of <code class="docutils literal notranslate"><span class="pre">List[float]</span></code>, formed by all lists that contain only real numbers. The first condition of subtyping holds, but appending a real number only works with <code class="docutils literal notranslate"><span class="pre">List[float]</span></code> so that the second condition fails:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">append_pi</span><span class="p">(</span><span class="n">lst</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">float</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="n">lst</span> <span class="o">+=</span> <span class="p">[</span><span class="mf">3.14</span><span class="p">]</span> <span class="n">my_list</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span> <span class="c1"># type: List[int]</span> <span class="n">append_pi</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span> <span class="c1"># Naively, this should be safe...</span> <span class="n">my_list</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">5</span> <span class="c1"># ... but this fails</span> </pre></div> </div> <p>There are two widespread approaches to <em>declare</em> subtype information to type checker.</p> <p>In nominal subtyping, the type tree is based on the class tree, i.e., <code class="docutils literal notranslate"><span class="pre">UserID</span></code> is considered a subtype of <code class="docutils literal notranslate"><span class="pre">int</span></code>. This approach should be used under control of the type checker, because in Python one can override attributes in an incompatible way:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="p">:</span> <span class="n">answer</span> <span class="o">=</span> <span class="s1">'42'</span> <span class="c1"># type: str</span> <span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span> <span class="n">answer</span> <span class="o">=</span> <span class="mi">5</span> <span class="c1"># should be marked as error by type checker</span> </pre></div> </div> <p>In structural subtyping the subtype relation is deduced from the declared methods, i.e., <code class="docutils literal notranslate"><span class="pre">UserID</span></code> and <code class="docutils literal notranslate"><span class="pre">int</span></code> would be considered the same type. While this may occasionally cause confusion, structural subtyping is considered more flexible. We strive to provide support for both approaches, so that structural information can be used in addition to nominal subtyping.</p> </section> </section> <section id="summary-of-gradual-typing"> <span id="pep-483-gradual-typing"></span><h2><a class="toc-backref" href="#summary-of-gradual-typing" role="doc-backlink">Summary of gradual typing</a></h2> <p>Gradual typing allows one to annotate only part of a program, thus leverage desirable aspects of both dynamic and static typing.</p> <p>We define a new relationship, is-consistent-with, which is similar to is-subtype-of, except it is not transitive when the new type <code class="docutils literal notranslate"><span class="pre">Any</span></code> is involved. (Neither relationship is symmetric.) Assigning <code class="docutils literal notranslate"><span class="pre">a_value</span></code> to <code class="docutils literal notranslate"><span class="pre">a_variable</span></code> is OK if the type of <code class="docutils literal notranslate"><span class="pre">a_value</span></code> is consistent with the type of <code class="docutils literal notranslate"><span class="pre">a_variable</span></code>. (Compare this to “… if the type of <code class="docutils literal notranslate"><span class="pre">a_value</span></code> is a subtype of the type of <code class="docutils literal notranslate"><span class="pre">a_variable</span></code>”, which states one of the fundamentals of OO programming.) The is-consistent-with relationship is defined by three rules:</p> <ul class="simple"> <li>A type <code class="docutils literal notranslate"><span class="pre">t1</span></code> is consistent with a type <code class="docutils literal notranslate"><span class="pre">t2</span></code> if <code class="docutils literal notranslate"><span class="pre">t1</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">t2</span></code>. (But not the other way around.)</li> <li><code class="docutils literal notranslate"><span class="pre">Any</span></code> is consistent with every type. (But <code class="docutils literal notranslate"><span class="pre">Any</span></code> is not a subtype of every type.)</li> <li>Every type is consistent with <code class="docutils literal notranslate"><span class="pre">Any</span></code>. (But every type is not a subtype of <code class="docutils literal notranslate"><span class="pre">Any</span></code>.)</li> </ul> <p>That’s all! See Jeremy Siek’s blog post <a class="reference external" href="http://wphomes.soic.indiana.edu/jsiek/what-is-gradual-typing/">What is Gradual Typing</a> for a longer explanation and motivation. <code class="docutils literal notranslate"><span class="pre">Any</span></code> can be considered a type that has all values and all methods. Combined with the definition of subtyping above, this places <code class="docutils literal notranslate"><span class="pre">Any</span></code> partially at the top (it has all values) and bottom (it has all methods) of the type hierarchy. Contrast this to <code class="docutils literal notranslate"><span class="pre">object</span></code> – it is not consistent with most types (e.g. you can’t use an <code class="docutils literal notranslate"><span class="pre">object()</span></code> instance where an <code class="docutils literal notranslate"><span class="pre">int</span></code> is expected). IOW both <code class="docutils literal notranslate"><span class="pre">Any</span></code> and <code class="docutils literal notranslate"><span class="pre">object</span></code> mean “any type is allowed” when used to annotate an argument, but only <code class="docutils literal notranslate"><span class="pre">Any</span></code> can be passed no matter what type is expected (in essence, <code class="docutils literal notranslate"><span class="pre">Any</span></code> declares a fallback to dynamic typing and shuts up complaints from the static checker).</p> <p>Here’s an example showing how these rules work out in practice:</p> <p>Say we have an <code class="docutils literal notranslate"><span class="pre">Employee</span></code> class, and a subclass <code class="docutils literal notranslate"><span class="pre">Manager</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Employee</span><span class="p">:</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">Manager</span><span class="p">(</span><span class="n">Employee</span><span class="p">):</span> <span class="o">...</span> </pre></div> </div> <p>Let’s say variable <code class="docutils literal notranslate"><span class="pre">worker</span></code> is declared with type <code class="docutils literal notranslate"><span class="pre">Employee</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">worker</span> <span class="o">=</span> <span class="n">Employee</span><span class="p">()</span> <span class="c1"># type: Employee</span> </pre></div> </div> <p>Now it’s okay to assign a <code class="docutils literal notranslate"><span class="pre">Manager</span></code> instance to <code class="docutils literal notranslate"><span class="pre">worker</span></code> (rule 1):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">worker</span> <span class="o">=</span> <span class="n">Manager</span><span class="p">()</span> </pre></div> </div> <p>It’s not okay to assign an <code class="docutils literal notranslate"><span class="pre">Employee</span></code> instance to a variable declared with type <code class="docutils literal notranslate"><span class="pre">Manager</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">boss</span> <span class="o">=</span> <span class="n">Manager</span><span class="p">()</span> <span class="c1"># type: Manager</span> <span class="n">boss</span> <span class="o">=</span> <span class="n">Employee</span><span class="p">()</span> <span class="c1"># Fails static check</span> </pre></div> </div> <p>However, suppose we have a variable whose type is <code class="docutils literal notranslate"><span class="pre">Any</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">something</span> <span class="o">=</span> <span class="n">some_func</span><span class="p">()</span> <span class="c1"># type: Any</span> </pre></div> </div> <p>Now it’s okay to assign <code class="docutils literal notranslate"><span class="pre">something</span></code> to <code class="docutils literal notranslate"><span class="pre">worker</span></code> (rule 2):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">worker</span> <span class="o">=</span> <span class="n">something</span> <span class="c1"># OK</span> </pre></div> </div> <p>Of course it’s also okay to assign <code class="docutils literal notranslate"><span class="pre">worker</span></code> to <code class="docutils literal notranslate"><span class="pre">something</span></code> (rule 3), but we didn’t need the concept of consistency for that:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">something</span> <span class="o">=</span> <span class="n">worker</span> <span class="c1"># OK</span> </pre></div> </div> <section id="types-vs-classes"> <h3><a class="toc-backref" href="#types-vs-classes" role="doc-backlink">Types vs. Classes</a></h3> <p>In Python, classes are object factories defined by the <code class="docutils literal notranslate"><span class="pre">class</span></code> statement, and returned by the <code class="docutils literal notranslate"><span class="pre">type(obj)</span></code> built-in function. Class is a dynamic, runtime concept.</p> <p>Type concept is described above, types appear in variable and function type annotations, can be constructed from building blocks described below, and are used by static type checkers.</p> <p>Every class is a type as discussed above. But it is tricky and error prone to implement a class that exactly represents semantics of a given type, and it is not a goal of <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>. <em>The static types described in</em> <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> <em>should not be confused with the runtime classes.</em> Examples:</p> <ul> <li><code class="docutils literal notranslate"><span class="pre">int</span></code> is a class and a type.</li> <li><code class="docutils literal notranslate"><span class="pre">UserID</span></code> is a class and a type.</li> <li><code class="docutils literal notranslate"><span class="pre">Union[str,</span> <span class="pre">int]</span></code> is a type but not a proper class:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyUnion</span><span class="p">(</span><span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">int</span><span class="p">]):</span> <span class="o">...</span> <span class="c1"># raises TypeError</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">int</span><span class="p">]()</span> <span class="c1"># raises TypeError</span> </pre></div> </div> </li> </ul> <p>Typing interface is implemented with classes, i.e., at runtime it is possible to evaluate, e.g., <code class="docutils literal notranslate"><span class="pre">Generic[T].__bases__</span></code>. But to emphasize the distinction between classes and types the following general rules apply:</p> <ul class="simple"> <li>No types defined below (i.e. <code class="docutils literal notranslate"><span class="pre">Any</span></code>, <code class="docutils literal notranslate"><span class="pre">Union</span></code>, etc.) can be instantiated, an attempt to do so will raise <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>. (But non-abstract subclasses of <code class="docutils literal notranslate"><span class="pre">Generic</span></code> can be.)</li> <li>No types defined below can be subclassed, except for <code class="docutils literal notranslate"><span class="pre">Generic</span></code> and classes derived from it.</li> <li>All of these will raise <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> if they appear in <code class="docutils literal notranslate"><span class="pre">isinstance</span></code> or <code class="docutils literal notranslate"><span class="pre">issubclass</span></code> (except for unparameterized generics).</li> </ul> </section> <section id="fundamental-building-blocks"> <h3><a class="toc-backref" href="#fundamental-building-blocks" role="doc-backlink">Fundamental building blocks</a></h3> <ul class="simple"> <li><strong>Any</strong>. Every type is consistent with <code class="docutils literal notranslate"><span class="pre">Any</span></code>; and it is also consistent with every type (see above).</li> <li><strong>Union[t1, t2, …]</strong>. Types that are subtype of at least one of <code class="docutils literal notranslate"><span class="pre">t1</span></code> etc. are subtypes of this.<ul> <li>Unions whose components are all subtypes of <code class="docutils literal notranslate"><span class="pre">t1</span></code> etc. are subtypes of this. Example: <code class="docutils literal notranslate"><span class="pre">Union[int,</span> <span class="pre">str]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Union[int,</span> <span class="pre">float,</span> <span class="pre">str]</span></code>.</li> <li>The order of the arguments doesn’t matter. Example: <code class="docutils literal notranslate"><span class="pre">Union[int,</span> <span class="pre">str]</span> <span class="pre">==</span> <span class="pre">Union[str,</span> <span class="pre">int]</span></code>.</li> <li>If <code class="docutils literal notranslate"><span class="pre">ti</span></code> is itself a <code class="docutils literal notranslate"><span class="pre">Union</span></code> the result is flattened. Example: <code class="docutils literal notranslate"><span class="pre">Union[int,</span> <span class="pre">Union[float,</span> <span class="pre">str]]</span> <span class="pre">==</span> <span class="pre">Union[int,</span> <span class="pre">float,</span> <span class="pre">str]</span></code>.</li> <li>If <code class="docutils literal notranslate"><span class="pre">ti</span></code> and <code class="docutils literal notranslate"><span class="pre">tj</span></code> have a subtype relationship, the less specific type survives. Example: <code class="docutils literal notranslate"><span class="pre">Union[Employee,</span> <span class="pre">Manager]</span> <span class="pre">==</span> <span class="pre">Union[Employee]</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">Union[t1]</span></code> returns just <code class="docutils literal notranslate"><span class="pre">t1</span></code>. <code class="docutils literal notranslate"><span class="pre">Union[]</span></code> is illegal, so is <code class="docutils literal notranslate"><span class="pre">Union[()]</span></code></li> <li>Corollary: <code class="docutils literal notranslate"><span class="pre">Union[...,</span> <span class="pre">object,</span> <span class="pre">...]</span></code> returns <code class="docutils literal notranslate"><span class="pre">object</span></code>.</li> </ul> </li> <li><strong>Optional[t1]</strong>. Alias for <code class="docutils literal notranslate"><span class="pre">Union[t1,</span> <span class="pre">None]</span></code>, i.e. <code class="docutils literal notranslate"><span class="pre">Union[t1,</span> <span class="pre">type(None)]</span></code>.</li> <li><strong>Tuple[t1, t2, …, tn]</strong>. A tuple whose items are instances of <code class="docutils literal notranslate"><span class="pre">t1</span></code>, etc. Example: <code class="docutils literal notranslate"><span class="pre">Tuple[int,</span> <span class="pre">float]</span></code> means a tuple of two items, the first is an <code class="docutils literal notranslate"><span class="pre">int</span></code>, the second is a <code class="docutils literal notranslate"><span class="pre">float</span></code>; e.g., <code class="docutils literal notranslate"><span class="pre">(42,</span> <span class="pre">3.14)</span></code>.<ul> <li><code class="docutils literal notranslate"><span class="pre">Tuple[u1,</span> <span class="pre">u2,</span> <span class="pre">...,</span> <span class="pre">um]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Tuple[t1,</span> <span class="pre">t2,</span> <span class="pre">...,</span> <span class="pre">tn]</span></code> if they have the same length <code class="docutils literal notranslate"><span class="pre">n==m</span></code> and each <code class="docutils literal notranslate"><span class="pre">ui</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">ti</span></code>.</li> <li>To spell the type of the empty tuple, use <code class="docutils literal notranslate"><span class="pre">Tuple[()]</span></code>.</li> <li>A variadic homogeneous tuple type can be written <code class="docutils literal notranslate"><span class="pre">Tuple[t1,</span> <span class="pre">...]</span></code>. (That’s three dots, a literal ellipsis; and yes, that’s a valid token in Python’s syntax.)</li> </ul> </li> <li><strong>Callable[[t1, t2, …, tn], tr]</strong>. A function with positional argument types <code class="docutils literal notranslate"><span class="pre">t1</span></code> etc., and return type <code class="docutils literal notranslate"><span class="pre">tr</span></code>. The argument list may be empty <code class="docutils literal notranslate"><span class="pre">n==0</span></code>. There is no way to indicate optional or keyword arguments, nor varargs, but you can say the argument list is entirely unchecked by writing <code class="docutils literal notranslate"><span class="pre">Callable[...,</span> <span class="pre">tr]</span></code> (again, a literal ellipsis).</li> </ul> <p>We might add:</p> <ul class="simple"> <li><strong>Intersection[t1, t2, …]</strong>. Types that are subtype of <em>each</em> of <code class="docutils literal notranslate"><span class="pre">t1</span></code>, etc are subtypes of this. (Compare to <code class="docutils literal notranslate"><span class="pre">Union</span></code>, which has <em>at least one</em> instead of <em>each</em> in its definition.)<ul> <li>The order of the arguments doesn’t matter. Nested intersections are flattened, e.g. <code class="docutils literal notranslate"><span class="pre">Intersection[int,</span> <span class="pre">Intersection[float,</span> <span class="pre">str]]</span> <span class="pre">==</span> <span class="pre">Intersection[int,</span> <span class="pre">float,</span> <span class="pre">str]</span></code>.</li> <li>An intersection of fewer types is a supertype of an intersection of more types, e.g. <code class="docutils literal notranslate"><span class="pre">Intersection[int,</span> <span class="pre">str]</span></code> is a supertype of <code class="docutils literal notranslate"><span class="pre">Intersection[int,</span> <span class="pre">float,</span> <span class="pre">str]</span></code>.</li> <li>An intersection of one argument is just that argument, e.g. <code class="docutils literal notranslate"><span class="pre">Intersection[int]</span></code> is <code class="docutils literal notranslate"><span class="pre">int</span></code>.</li> <li>When argument have a subtype relationship, the more specific type survives, e.g. <code class="docutils literal notranslate"><span class="pre">Intersection[str,</span> <span class="pre">Employee,</span> <span class="pre">Manager]</span></code> is <code class="docutils literal notranslate"><span class="pre">Intersection[str,</span> <span class="pre">Manager]</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">Intersection[]</span></code> is illegal, so is <code class="docutils literal notranslate"><span class="pre">Intersection[()]</span></code>.</li> <li>Corollary: <code class="docutils literal notranslate"><span class="pre">Any</span></code> disappears from the argument list, e.g. <code class="docutils literal notranslate"><span class="pre">Intersection[int,</span> <span class="pre">str,</span> <span class="pre">Any]</span> <span class="pre">==</span> <span class="pre">Intersection[int,</span> <span class="pre">str]</span></code>. <code class="docutils literal notranslate"><span class="pre">Intersection[Any,</span> <span class="pre">object]</span></code> is <code class="docutils literal notranslate"><span class="pre">object</span></code>.</li> <li>The interaction between <code class="docutils literal notranslate"><span class="pre">Intersection</span></code> and <code class="docutils literal notranslate"><span class="pre">Union</span></code> is complex but should be no surprise if you understand the interaction between intersections and unions of regular sets (note that sets of types can be infinite in size, since there is no limit on the number of new subclasses).</li> </ul> </li> </ul> </section> </section> <section id="generic-types"> <h2><a class="toc-backref" href="#generic-types" role="doc-backlink">Generic types</a></h2> <p>The fundamental building blocks defined above allow to construct new types in a generic manner. For example, <code class="docutils literal notranslate"><span class="pre">Tuple</span></code> can take a concrete type <code class="docutils literal notranslate"><span class="pre">float</span></code> and make a concrete type <code class="docutils literal notranslate"><span class="pre">Vector</span> <span class="pre">=</span> <span class="pre">Tuple[float,</span> <span class="pre">...]</span></code>, or it can take another type <code class="docutils literal notranslate"><span class="pre">UserID</span></code> and make another concrete type <code class="docutils literal notranslate"><span class="pre">Registry</span> <span class="pre">=</span> <span class="pre">Tuple[UserID,</span> <span class="pre">...]</span></code>. Such semantics is known as generic type constructor, it is similar to semantics of functions, but a function takes a value and returns a value, while generic type constructor takes a type and “returns” a type.</p> <p>It is common when a particular class or a function behaves in such a type generic manner. Consider two examples:</p> <ul> <li>Container classes, such as <code class="docutils literal notranslate"><span class="pre">list</span></code> or <code class="docutils literal notranslate"><span class="pre">dict</span></code>, typically contain only values of a particular type. Therefore, a user might want to type annotate them as such:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">users</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: List[UserID]</span> <span class="n">users</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">UserID</span><span class="p">(</span><span class="mi">42</span><span class="p">))</span> <span class="c1"># OK</span> <span class="n">users</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'Some guy'</span><span class="p">)</span> <span class="c1"># Should be rejected by the type checker</span> <span class="n">examples</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># type: Dict[str, Any]</span> <span class="n">examples</span><span class="p">[</span><span class="s1">'first example'</span><span class="p">]</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span> <span class="c1"># OK</span> <span class="n">examples</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># rejected by the type checker</span> </pre></div> </div> </li> <li>The following function can take two arguments of type <code class="docutils literal notranslate"><span class="pre">int</span></code> and return an <code class="docutils literal notranslate"><span class="pre">int</span></code>, or take two arguments of type <code class="docutils literal notranslate"><span class="pre">float</span></code> and return a <code class="docutils literal notranslate"><span class="pre">float</span></code>, etc.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">add</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="n">add</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="o">==</span> <span class="mi">3</span> <span class="n">add</span><span class="p">(</span><span class="s1">'1'</span><span class="p">,</span> <span class="s1">'2'</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'12'</span> <span class="n">add</span><span class="p">(</span><span class="mf">2.7</span><span class="p">,</span> <span class="mf">3.5</span><span class="p">)</span> <span class="o">==</span> <span class="mf">6.2</span> </pre></div> </div> </li> </ul> <p>To allow type annotations in situations from the first example, built-in containers and container abstract base classes are extended with type parameters, so that they behave as generic type constructors. Classes, that behave as generic type constructors are called <em>generic types</em>. Example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Iterable</span> <span class="k">class</span><span class="w"> </span><span class="nc">Task</span><span class="p">:</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">work</span><span class="p">(</span><span class="n">todo_list</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Task</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>Here <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> is a generic type that takes a concrete type <code class="docutils literal notranslate"><span class="pre">Task</span></code> and returns a concrete type <code class="docutils literal notranslate"><span class="pre">Iterable[Task]</span></code>.</p> <p>Functions that behave in the type generic manner (as in second example) are called <em>generic functions</em>. Type annotations of generic functions are allowed by <em>type variables</em>. Their semantics with respect to generic types is somewhat similar to semantics of parameters in functions. But one does not assign concrete types to type variables, it is the task of a static type checker to find their possible values and warn the user if it cannot find. Example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">take_first</span><span class="p">(</span><span class="n">seq</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="c1"># a generic function</span> <span class="k">return</span> <span class="n">seq</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">accumulator</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># type: int</span> <span class="n">accumulator</span> <span class="o">+=</span> <span class="n">take_first</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"># Safe, T deduced to be int</span> <span class="n">accumulator</span> <span class="o">+=</span> <span class="n">take_first</span><span class="p">((</span><span class="mf">2.7</span><span class="p">,</span> <span class="mf">3.5</span><span class="p">))</span> <span class="c1"># Unsafe</span> </pre></div> </div> <p>Type variables are used extensively in type annotations, also internal machinery of the type inference in type checkers is typically build on type variables. Therefore, let us consider them in detail.</p> <section id="type-variables"> <h3><a class="toc-backref" href="#type-variables" role="doc-backlink">Type variables</a></h3> <p><code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">=</span> <span class="pre">TypeVar('X')</span></code> declares a unique type variable. The name must match the variable name. By default, a type variable ranges over all possible types. Example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">do_nothing</span><span class="p">(</span><span class="n">one_arg</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">other_arg</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="k">pass</span> <span class="n">do_nothing</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="c1"># OK, T is int</span> <span class="n">do_nothing</span><span class="p">(</span><span class="s1">'abc'</span><span class="p">,</span> <span class="n">UserID</span><span class="p">(</span><span class="mi">42</span><span class="p">))</span> <span class="c1"># also OK, T is object</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">Y</span> <span class="pre">=</span> <span class="pre">TypeVar('Y',</span> <span class="pre">t1,</span> <span class="pre">t2,</span> <span class="pre">...)</span></code>. Ditto, constrained to <code class="docutils literal notranslate"><span class="pre">t1</span></code>, etc. Behaves similar to <code class="docutils literal notranslate"><span class="pre">Union[t1,</span> <span class="pre">t2,</span> <span class="pre">...]</span></code>. A constrained type variable ranges only over constrains <code class="docutils literal notranslate"><span class="pre">t1</span></code>, etc. <em>exactly</em>; subclasses of the constrains are replaced by the most-derived base class among <code class="docutils literal notranslate"><span class="pre">t1</span></code>, etc. Examples:</p> <ul> <li>Function type annotation with a constrained type variable:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">AnyStr</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'AnyStr'</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">longest</span><span class="p">(</span><span class="n">first</span><span class="p">:</span> <span class="n">AnyStr</span><span class="p">,</span> <span class="n">second</span><span class="p">:</span> <span class="n">AnyStr</span><span class="p">)</span> <span class="o">-></span> <span class="n">AnyStr</span><span class="p">:</span> <span class="k">return</span> <span class="n">first</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">first</span><span class="p">)</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">second</span><span class="p">)</span> <span class="k">else</span> <span class="n">second</span> <span class="n">result</span> <span class="o">=</span> <span class="n">longest</span><span class="p">(</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'abc'</span><span class="p">)</span> <span class="c1"># The inferred type for result is str</span> <span class="n">result</span> <span class="o">=</span> <span class="n">longest</span><span class="p">(</span><span class="s1">'a'</span><span class="p">,</span> <span class="sa">b</span><span class="s1">'abc'</span><span class="p">)</span> <span class="c1"># Fails static type check</span> </pre></div> </div> <p>In this example, both arguments to <code class="docutils literal notranslate"><span class="pre">longest()</span></code> must have the same type (<code class="docutils literal notranslate"><span class="pre">str</span></code> or <code class="docutils literal notranslate"><span class="pre">bytes</span></code>), and moreover, even if the arguments are instances of a common <code class="docutils literal notranslate"><span class="pre">str</span></code> subclass, the return type is still <code class="docutils literal notranslate"><span class="pre">str</span></code>, not that subclass (see next example).</p> </li> <li>For comparison, if the type variable was unconstrained, the common subclass would be chosen as the return type, e.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">S</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'S'</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">longest</span><span class="p">(</span><span class="n">first</span><span class="p">:</span> <span class="n">S</span><span class="p">,</span> <span class="n">second</span><span class="p">:</span> <span class="n">S</span><span class="p">)</span> <span class="o">-></span> <span class="n">S</span><span class="p">:</span> <span class="k">return</span> <span class="n">first</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">first</span><span class="p">)</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">second</span><span class="p">)</span> <span class="k">else</span> <span class="n">second</span> <span class="k">class</span><span class="w"> </span><span class="nc">MyStr</span><span class="p">(</span><span class="nb">str</span><span class="p">):</span> <span class="o">...</span> <span class="n">result</span> <span class="o">=</span> <span class="n">longest</span><span class="p">(</span><span class="n">MyStr</span><span class="p">(</span><span class="s1">'a'</span><span class="p">),</span> <span class="n">MyStr</span><span class="p">(</span><span class="s1">'abc'</span><span class="p">))</span> </pre></div> </div> <p>The inferred type of <code class="docutils literal notranslate"><span class="pre">result</span></code> is <code class="docutils literal notranslate"><span class="pre">MyStr</span></code> (whereas in the <code class="docutils literal notranslate"><span class="pre">AnyStr</span></code> example it would be <code class="docutils literal notranslate"><span class="pre">str</span></code>).</p> </li> <li>Also for comparison, if a <code class="docutils literal notranslate"><span class="pre">Union</span></code> is used, the return type also has to be a <code class="docutils literal notranslate"><span class="pre">Union</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">U</span> <span class="o">=</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">]</span> <span class="k">def</span><span class="w"> </span><span class="nf">longest</span><span class="p">(</span><span class="n">first</span><span class="p">:</span> <span class="n">U</span><span class="p">,</span> <span class="n">second</span><span class="p">:</span> <span class="n">U</span><span class="p">)</span> <span class="o">-></span> <span class="n">U</span><span class="p">:</span> <span class="k">return</span> <span class="n">first</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">first</span><span class="p">)</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="n">second</span><span class="p">)</span> <span class="k">else</span> <span class="n">second</span> <span class="n">result</span> <span class="o">=</span> <span class="n">longest</span><span class="p">(</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'abc'</span><span class="p">)</span> </pre></div> </div> <p>The inferred type of <code class="docutils literal notranslate"><span class="pre">result</span></code> is still <code class="docutils literal notranslate"><span class="pre">Union[str,</span> <span class="pre">bytes]</span></code>, even though both arguments are <code class="docutils literal notranslate"><span class="pre">str</span></code>.</p> <p>Note that the type checker will reject this function:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">concat</span><span class="p">(</span><span class="n">first</span><span class="p">:</span> <span class="n">U</span><span class="p">,</span> <span class="n">second</span><span class="p">:</span> <span class="n">U</span><span class="p">)</span> <span class="o">-></span> <span class="n">U</span><span class="p">:</span> <span class="k">return</span> <span class="n">first</span> <span class="o">+</span> <span class="n">second</span> <span class="c1"># Error: can't concatenate str and bytes</span> </pre></div> </div> <p>For such cases where parameters could change their types only simultaneously one should use constrained type variables.</p> </li> </ul> </section> <section id="defining-and-using-generic-types"> <h3><a class="toc-backref" href="#defining-and-using-generic-types" role="doc-backlink">Defining and using generic types</a></h3> <p>Users can declare their classes as generic types using the special building block <code class="docutils literal notranslate"><span class="pre">Generic</span></code>. The definition <code class="docutils literal notranslate"><span class="pre">class</span> <span class="pre">MyGeneric(Generic[X,</span> <span class="pre">Y,</span> <span class="pre">...]):</span> <span class="pre">...</span></code> defines a generic type <code class="docutils literal notranslate"><span class="pre">MyGeneric</span></code> over type variables <code class="docutils literal notranslate"><span class="pre">X</span></code>, etc. <code class="docutils literal notranslate"><span class="pre">MyGeneric</span></code> itself becomes parameterizable, e.g. <code class="docutils literal notranslate"><span class="pre">MyGeneric[int,</span> <span class="pre">str,</span> <span class="pre">...]</span></code> is a specific type with substitutions <code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">-></span> <span class="pre">int</span></code>, etc. Example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">CustomQueue</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="w"> </span><span class="nf">put</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">task</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">communicate</span><span class="p">(</span><span class="n">queue</span><span class="p">:</span> <span class="n">CustomQueue</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span> <span class="o">...</span> </pre></div> </div> <p>Classes that derive from generic types become generic. A class can subclass multiple generic types. However, classes derived from specific types returned by generics are not generic. Examples:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">TodoList</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">Container</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span> <span class="k">def</span><span class="w"> </span><span class="nf">check</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="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">check_all</span><span class="p">(</span><span class="n">todo</span><span class="p">:</span> <span class="n">TodoList</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># TodoList is generic</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">URLList</span><span class="p">(</span><span class="n">Iterable</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]):</span> <span class="k">def</span><span class="w"> </span><span class="nf">scrape_all</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">urls</span><span class="p">:</span> <span class="n">URLList</span><span class="p">)</span> <span class="o">-></span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]</span> <span class="c1"># URLList is not generic</span> <span class="o">...</span> </pre></div> </div> <p>Subclassing a generic type imposes the subtype relation on the corresponding specific types, so that <code class="docutils literal notranslate"><span class="pre">TodoList[t1]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Iterable[t1]</span></code> in the above example.</p> <p>Generic types can be specialized (indexed) in several steps. Every type variable could be substituted by a specific type or by another generic type. If <code class="docutils literal notranslate"><span class="pre">Generic</span></code> appears in the base class list, then it should contain all type variables, and the order of type parameters is determined by the order in which they appear in <code class="docutils literal notranslate"><span class="pre">Generic</span></code>. Examples:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Table</span> <span class="o">=</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">T</span><span class="p">]</span> <span class="c1"># Table is generic</span> <span class="n">Messages</span> <span class="o">=</span> <span class="n">Table</span><span class="p">[</span><span class="nb">bytes</span><span class="p">]</span> <span class="c1"># Same as Dict[int, bytes]</span> <span class="k">class</span><span class="w"> </span><span class="nc">BaseGeneric</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="n">S</span><span class="p">]):</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">DerivedGeneric</span><span class="p">(</span><span class="n">BaseGeneric</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">T</span><span class="p">]):</span> <span class="c1"># DerivedGeneric has one parameter</span> <span class="o">...</span> <span class="n">SpecificType</span> <span class="o">=</span> <span class="n">DerivedGeneric</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="c1"># OK</span> <span class="k">class</span><span class="w"> </span><span class="nc">MyDictView</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">S</span><span class="p">,</span> <span class="n">T</span><span class="p">,</span> <span class="n">U</span><span class="p">],</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">U</span><span class="p">,</span> <span class="n">T</span><span class="p">]]):</span> <span class="o">...</span> <span class="n">Example</span> <span class="o">=</span> <span class="n">MyDictView</span><span class="p">[</span><span class="nb">list</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">str</span><span class="p">]</span> <span class="c1"># S -> list, T -> int, U -> str</span> </pre></div> </div> <p>If a generic type appears in a type annotation with a type variable omitted, it is assumed to be <code class="docutils literal notranslate"><span class="pre">Any</span></code>. Such form could be used as a fallback to dynamic typing and is allowed for use with <code class="docutils literal notranslate"><span class="pre">issubclass</span></code> and <code class="docutils literal notranslate"><span class="pre">isinstance</span></code>. All type information in instances is erased at runtime. Examples:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">count</span><span class="p">(</span><span class="n">seq</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span> <span class="c1"># Same as Sequence[Any]</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">FrameworkBase</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">S</span><span class="p">,</span> <span class="n">T</span><span class="p">]):</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">UserClass</span><span class="p">:</span> <span class="o">...</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">UserClass</span><span class="p">,</span> <span class="n">FrameworkBase</span><span class="p">)</span> <span class="c1"># This is OK</span> <span class="k">class</span><span class="w"> </span><span class="nc">Node</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="o">...</span> <span class="n">IntNode</span> <span class="o">=</span> <span class="n">Node</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="n">my_node</span> <span class="o">=</span> <span class="n">IntNode</span><span class="p">()</span> <span class="c1"># at runtime my_node.__class__ is Node</span> <span class="c1"># inferred static type of my_node is Node[int]</span> </pre></div> </div> </section> <section id="covariance-and-contravariance"> <h3><a class="toc-backref" href="#covariance-and-contravariance" role="doc-backlink">Covariance and Contravariance</a></h3> <p>If <code class="docutils literal notranslate"><span class="pre">t2</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">t1</span></code>, then a generic type constructor <code class="docutils literal notranslate"><span class="pre">GenType</span></code> is called:</p> <ul class="simple"> <li>Covariant, if <code class="docutils literal notranslate"><span class="pre">GenType[t2]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">GenType[t1]</span></code> for all such <code class="docutils literal notranslate"><span class="pre">t1</span></code> and <code class="docutils literal notranslate"><span class="pre">t2</span></code>.</li> <li>Contravariant, if <code class="docutils literal notranslate"><span class="pre">GenType[t1]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">GenType[t2]</span></code> for all such <code class="docutils literal notranslate"><span class="pre">t1</span></code> and <code class="docutils literal notranslate"><span class="pre">t2</span></code>.</li> <li>Invariant, if neither of the above is true.</li> </ul> <p>To better understand this definition, let us make an analogy with ordinary functions. Assume that we have:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">cov</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span> <span class="k">return</span> <span class="mi">2</span><span class="o">*</span><span class="n">x</span> <span class="k">def</span><span class="w"> </span><span class="nf">contra</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span> <span class="k">return</span> <span class="o">-</span><span class="n">x</span> <span class="k">def</span><span class="w"> </span><span class="nf">inv</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span> <span class="k">return</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span> </pre></div> </div> <p>If <code class="docutils literal notranslate"><span class="pre">x1</span> <span class="pre"><</span> <span class="pre">x2</span></code>, then <em>always</em> <code class="docutils literal notranslate"><span class="pre">cov(x1)</span> <span class="pre"><</span> <span class="pre">cov(x2)</span></code>, and <code class="docutils literal notranslate"><span class="pre">contra(x2)</span> <span class="pre"><</span> <span class="pre">contra(x1)</span></code>, while nothing could be said about <code class="docutils literal notranslate"><span class="pre">inv</span></code>. Replacing <code class="docutils literal notranslate"><span class="pre"><</span></code> with is-subtype-of, and functions with generic type constructor we get examples of covariant, contravariant, and invariant behavior. Let us now consider practical examples:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">Union</span></code> behaves covariantly in all its arguments. Indeed, as discussed above, <code class="docutils literal notranslate"><span class="pre">Union[t1,</span> <span class="pre">t2,</span> <span class="pre">...]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Union[u1,</span> <span class="pre">u2,</span> <span class="pre">...]</span></code>, if <code class="docutils literal notranslate"><span class="pre">t1</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">u1</span></code>, etc.</li> <li><code class="docutils literal notranslate"><span class="pre">FrozenSet[T]</span></code> is also covariant. Let us consider <code class="docutils literal notranslate"><span class="pre">int</span></code> and <code class="docutils literal notranslate"><span class="pre">float</span></code> in place of <code class="docutils literal notranslate"><span class="pre">T</span></code>. First, <code class="docutils literal notranslate"><span class="pre">int</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">float</span></code>. Second, set of values of <code class="docutils literal notranslate"><span class="pre">FrozenSet[int]</span></code> is clearly a subset of values of <code class="docutils literal notranslate"><span class="pre">FrozenSet[float]</span></code>, while set of functions from <code class="docutils literal notranslate"><span class="pre">FrozenSet[float]</span></code> is a subset of set of functions from <code class="docutils literal notranslate"><span class="pre">FrozenSet[int]</span></code>. Therefore, by definition <code class="docutils literal notranslate"><span class="pre">FrozenSet[int]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">FrozenSet[float]</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">List[T]</span></code> is invariant. Indeed, although set of values of <code class="docutils literal notranslate"><span class="pre">List[int]</span></code> is a subset of values of <code class="docutils literal notranslate"><span class="pre">List[float]</span></code>, only <code class="docutils literal notranslate"><span class="pre">int</span></code> could be appended to a <code class="docutils literal notranslate"><span class="pre">List[int]</span></code>, as discussed in section “Background”. Therefore, <code class="docutils literal notranslate"><span class="pre">List[int]</span></code> is not a subtype of <code class="docutils literal notranslate"><span class="pre">List[float]</span></code>. This is a typical situation with mutable types, they are typically invariant.</li> </ul> <p>One of the best examples to illustrate (somewhat counterintuitive) contravariant behavior is the callable type. It is covariant in the return type, but contravariant in the arguments. For two callable types that differ only in the return type, the subtype relationship for the callable types follows that of the return types. Examples:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">Callable[[],</span> <span class="pre">int]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Callable[[],</span> <span class="pre">float]</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">Callable[[],</span> <span class="pre">Manager]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Callable[[],</span> <span class="pre">Employee]</span></code>.</li> </ul> <p>While for two callable types that differ only in the type of one argument, the subtype relationship for the callable types goes <em>in the opposite direction</em> as for the argument types. Examples:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">Callable[[float],</span> <span class="pre">None]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Callable[[int],</span> <span class="pre">None]</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">Callable[[Employee],</span> <span class="pre">None]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Callable[[Manager],</span> <span class="pre">None]</span></code>.</li> </ul> <p>Yes, you read that right. Indeed, if a function that can calculate the salary for a manager is expected:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">calculate_all</span><span class="p">(</span><span class="n">lst</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Manager</span><span class="p">],</span> <span class="n">salary</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="n">Manager</span><span class="p">],</span> <span class="n">Decimal</span><span class="p">]):</span> <span class="o">...</span> </pre></div> </div> <p>then <code class="docutils literal notranslate"><span class="pre">Callable[[Employee],</span> <span class="pre">Decimal]</span></code> that can calculate a salary for any employee is also acceptable.</p> <p>The example with <code class="docutils literal notranslate"><span class="pre">Callable</span></code> shows how to make more precise type annotations for functions: choose the most general type for every argument, and the most specific type for the return value.</p> <p>It is possible to <em>declare</em> the variance for user defined generic types by using special keywords <code class="docutils literal notranslate"><span class="pre">covariant</span></code> and <code class="docutils literal notranslate"><span class="pre">contravariant</span></code> in the definition of type variables used as parameters. Types are invariant by default. 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">'T'</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">'T_co'</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">'T_contra'</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="w"> </span><span class="nc">LinkedList</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="c1"># invariant by default</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">append</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">element</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">Box</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T_co</span><span class="p">]):</span> <span class="c1"># this type is declared covariant</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="n">T_co</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span> <span class="o">=</span> <span class="n">content</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_content</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">T_co</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span> <span class="k">class</span><span class="w"> </span><span class="nc">Sink</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T_contra</span><span class="p">]):</span> <span class="c1"># this type is declared contravariant</span> <span class="k">def</span><span class="w"> </span><span class="nf">send_to_nowhere</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">-></span> <span class="kc">None</span><span class="p">:</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">devnull</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">devnull</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">devnull</span><span class="p">)</span> </pre></div> </div> <p>Note, that although the variance is defined via type variables, it is not a property of type variables, but a property of generic types. In complex definitions of derived generics, variance <em>only</em> determined from type variables used. A complex example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T_co</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T_co'</span><span class="p">,</span> <span class="n">Employee</span><span class="p">,</span> <span class="n">Manager</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">'T_contra'</span><span class="p">,</span> <span class="n">Employee</span><span class="p">,</span> <span class="n">Manager</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="w"> </span><span class="nc">Base</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T_contra</span><span class="p">]):</span> <span class="o">...</span> <span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">[</span><span class="n">T_co</span><span class="p">]):</span> <span class="o">...</span> </pre></div> </div> <p>A type checker finds from the second declaration that <code class="docutils literal notranslate"><span class="pre">Derived[Manager]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Derived[Employee]</span></code>, and <code class="docutils literal notranslate"><span class="pre">Derived[t1]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Base[t1]</span></code>. If we denote the is-subtype-of relationship with <code class="docutils literal notranslate"><span class="pre"><</span></code>, then the full diagram of subtyping for this case will be:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Base</span><span class="p">[</span><span class="n">Manager</span><span class="p">]</span> <span class="o">></span> <span class="n">Base</span><span class="p">[</span><span class="n">Employee</span><span class="p">]</span> <span class="n">v</span> <span class="n">v</span> <span class="n">Derived</span><span class="p">[</span><span class="n">Manager</span><span class="p">]</span> <span class="o"><</span> <span class="n">Derived</span><span class="p">[</span><span class="n">Employee</span><span class="p">]</span> </pre></div> </div> <p>so that a type checker will also find that, e.g., <code class="docutils literal notranslate"><span class="pre">Derived[Manager]</span></code> is a subtype of <code class="docutils literal notranslate"><span class="pre">Base[Employee]</span></code>.</p> <p>For more information on type variables, generic types, and variance, see <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>, the <a class="reference external" href="http://mypy.readthedocs.io/en/latest/generics.html">mypy docs on generics</a>, and <a class="reference external" href="http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29">Wikipedia</a>.</p> </section> </section> <section id="pragmatics"> <h2><a class="toc-backref" href="#pragmatics" role="doc-backlink">Pragmatics</a></h2> <p>Some things are irrelevant to the theory but make practical use more convenient. (This is not a full list; I probably missed a few and some are still controversial or not fully specified.)</p> <ul> <li>Where a type is expected, <code class="docutils literal notranslate"><span class="pre">None</span></code> can be substituted for <code class="docutils literal notranslate"><span class="pre">type(None)</span></code>; e.g. <code class="docutils literal notranslate"><span class="pre">Union[t1,</span> <span class="pre">None]</span> <span class="pre">==</span> <span class="pre">Union[t1,</span> <span class="pre">type(None)]</span></code>.</li> <li>Type aliases, e.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Point</span> <span class="o">=</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">float</span><span class="p">,</span> <span class="nb">float</span><span class="p">]</span> <span class="k">def</span><span class="w"> </span><span class="nf">distance</span><span class="p">(</span><span class="n">point</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> </li> <li>Forward references via strings, e.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyComparable</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="nf">compare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">:</span> <span class="s1">'MyComparable'</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> </li> <li>Type variables can be declared in unconstrained, constrained, or bounded form. The variance of a generic type can also be indicated using a type variable declared with special keyword arguments, thus avoiding any special syntax, e.g.:<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">'T'</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="nb">complex</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">add</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="n">y</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="n">T_co</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T_co'</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="k">class</span><span class="w"> </span><span class="nc">ImmutableList</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T_co</span><span class="p">]):</span> <span class="o">...</span> </pre></div> </div> </li> <li>Type declaration in comments, e.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">lst</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: Sequence[int]</span> </pre></div> </div> </li> <li>Casts using <code class="docutils literal notranslate"><span class="pre">cast(T,</span> <span class="pre">obj)</span></code>, e.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zork</span> <span class="o">=</span> <span class="n">cast</span><span class="p">(</span><span class="n">Any</span><span class="p">,</span> <span class="n">frobozz</span><span class="p">())</span> </pre></div> </div> </li> <li>Other things, e.g. overloading and stub modules, see <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>.</li> </ul> <section id="predefined-generic-types-and-protocols-in-typing-py"> <h3><a class="toc-backref" href="#predefined-generic-types-and-protocols-in-typing-py" role="doc-backlink">Predefined generic types and Protocols in typing.py</a></h3> <p>(See also the <a class="reference external" href="https://github.com/python/typing/blob/master/src/typing.py">typing.py module</a>.)</p> <ul class="simple"> <li>Everything from <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> (but <code class="docutils literal notranslate"><span class="pre">Set</span></code> renamed to <code class="docutils literal notranslate"><span class="pre">AbstractSet</span></code>).</li> <li><code class="docutils literal notranslate"><span class="pre">Dict</span></code>, <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">FrozenSet</span></code>, a few more.</li> <li><code class="docutils literal notranslate"><span class="pre">re.Pattern[AnyStr]</span></code>, <code class="docutils literal notranslate"><span class="pre">re.Match[AnyStr]</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">io.IO[AnyStr]</span></code>, <code class="docutils literal notranslate"><span class="pre">io.TextIO</span> <span class="pre">~</span> <span class="pre">io.IO[str]</span></code>, <code class="docutils literal notranslate"><span class="pre">io.BinaryIO</span> <span class="pre">~</span> <span class="pre">io.IO[bytes]</span></code>.</li> </ul> </section> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document is licensed under the <a class="reference external" href="http://www.opencontent.org/openpub/">Open Publication License</a>.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0483.rst">https://github.com/python/peps/blob/main/peps/pep-0483.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0483.rst">2025-02-01 08:59:27 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="#introduction">Introduction</a><ul> <li><a class="reference internal" href="#notational-conventions">Notational conventions</a></li> </ul> </li> <li><a class="reference internal" href="#background">Background</a><ul> <li><a class="reference internal" href="#subtype-relationships">Subtype relationships</a></li> </ul> </li> <li><a class="reference internal" href="#summary-of-gradual-typing">Summary of gradual typing</a><ul> <li><a class="reference internal" href="#types-vs-classes">Types vs. Classes</a></li> <li><a class="reference internal" href="#fundamental-building-blocks">Fundamental building blocks</a></li> </ul> </li> <li><a class="reference internal" href="#generic-types">Generic types</a><ul> <li><a class="reference internal" href="#type-variables">Type variables</a></li> <li><a class="reference internal" href="#defining-and-using-generic-types">Defining and using generic types</a></li> <li><a class="reference internal" href="#covariance-and-contravariance">Covariance and Contravariance</a></li> </ul> </li> <li><a class="reference internal" href="#pragmatics">Pragmatics</a><ul> <li><a class="reference internal" href="#predefined-generic-types-and-protocols-in-typing-py">Predefined generic types and Protocols in typing.py</a></li> </ul> </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-0483.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>