2458 lines
242 KiB
HTML
2458 lines
242 KiB
HTML
|
||
<!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 484 – Type Hints | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0484/">
|
||
<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 484 – Type Hints | peps.python.org'>
|
||
<meta property="og:description" content="PEP 3107 introduced syntax for function annotations, but the semantics were deliberately left undefined. There has now been enough 3rd party usage for static type analysis that the community would benefit from a standard vocabulary and baseline tools w...">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0484/">
|
||
<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="PEP 3107 introduced syntax for function annotations, but the semantics were deliberately left undefined. There has now been enough 3rd party usage for static type analysis that the community would benefit from a standard vocabulary and baseline tools w...">
|
||
<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 484</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 484 – 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>, Jukka Lehtosalo <jukka.lehtosalo at iki.fi>, Łukasz Langa <lukasz at python.org></dd>
|
||
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
|
||
<dd class="field-even">Mark Shannon</dd>
|
||
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/python-dev@python.org/">Python-Dev list</a></dd>
|
||
<dt class="field-even">Status<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
||
<dt class="field-odd">Type<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
||
<dt class="field-even">Topic<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="../topic/typing/">Typing</a></dd>
|
||
<dt class="field-odd">Created<span class="colon">:</span></dt>
|
||
<dd class="field-odd">29-Sep-2014</dd>
|
||
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-even">3.5</dd>
|
||
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-odd">16-Jan-2015, 20-Mar-2015, 17-Apr-2015, 20-May-2015, 22-May-2015</dd>
|
||
<dt class="field-even">Resolution<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-May/140104.html">Python-Dev message</a></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a><ul>
|
||
<li><a class="reference internal" href="#non-goals">Non-goals</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-meaning-of-annotations">The meaning of annotations</a></li>
|
||
<li><a class="reference internal" href="#type-definition-syntax">Type Definition Syntax</a><ul>
|
||
<li><a class="reference internal" href="#acceptable-type-hints">Acceptable type hints</a></li>
|
||
<li><a class="reference internal" href="#using-none">Using None</a></li>
|
||
<li><a class="reference internal" href="#type-aliases">Type aliases</a></li>
|
||
<li><a class="reference internal" href="#callable">Callable</a></li>
|
||
<li><a class="reference internal" href="#generics">Generics</a></li>
|
||
<li><a class="reference internal" href="#user-defined-generic-types">User-defined generic types</a></li>
|
||
<li><a class="reference internal" href="#scoping-rules-for-type-variables">Scoping rules for type variables</a></li>
|
||
<li><a class="reference internal" href="#instantiating-generic-classes-and-type-erasure">Instantiating generic classes and type erasure</a></li>
|
||
<li><a class="reference internal" href="#arbitrary-generic-types-as-base-classes">Arbitrary generic types as base classes</a></li>
|
||
<li><a class="reference internal" href="#abstract-generic-types">Abstract generic types</a></li>
|
||
<li><a class="reference internal" href="#type-variables-with-an-upper-bound">Type variables with an upper bound</a></li>
|
||
<li><a class="reference internal" href="#covariance-and-contravariance">Covariance and contravariance</a></li>
|
||
<li><a class="reference internal" href="#the-numeric-tower">The numeric tower</a></li>
|
||
<li><a class="reference internal" href="#forward-references">Forward references</a></li>
|
||
<li><a class="reference internal" href="#union-types">Union types</a></li>
|
||
<li><a class="reference internal" href="#support-for-singleton-types-in-unions">Support for singleton types in unions</a></li>
|
||
<li><a class="reference internal" href="#the-any-type">The <code class="docutils literal notranslate"><span class="pre">Any</span></code> type</a></li>
|
||
<li><a class="reference internal" href="#the-noreturn-type">The <code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> type</a></li>
|
||
<li><a class="reference internal" href="#the-type-of-class-objects">The type of class objects</a></li>
|
||
<li><a class="reference internal" href="#annotating-instance-and-class-methods">Annotating instance and class methods</a></li>
|
||
<li><a class="reference internal" href="#version-and-platform-checking">Version and platform checking</a></li>
|
||
<li><a class="reference internal" href="#runtime-or-type-checking">Runtime or type checking?</a></li>
|
||
<li><a class="reference internal" href="#arbitrary-argument-lists-and-default-argument-values">Arbitrary argument lists and default argument values</a></li>
|
||
<li><a class="reference internal" href="#positional-only-arguments">Positional-only arguments</a></li>
|
||
<li><a class="reference internal" href="#annotating-generator-functions-and-coroutines">Annotating generator functions and coroutines</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#compatibility-with-other-uses-of-function-annotations">Compatibility with other uses of function annotations</a></li>
|
||
<li><a class="reference internal" href="#type-comments">Type comments</a></li>
|
||
<li><a class="reference internal" href="#casts">Casts</a></li>
|
||
<li><a class="reference internal" href="#newtype-helper-function">NewType helper function</a></li>
|
||
<li><a class="reference internal" href="#stub-files">Stub Files</a><ul>
|
||
<li><a class="reference internal" href="#function-method-overloading">Function/method overloading</a></li>
|
||
<li><a class="reference internal" href="#storing-and-distributing-stub-files">Storing and distributing stub files</a></li>
|
||
<li><a class="reference internal" href="#the-typeshed-repo">The Typeshed Repo</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#exceptions">Exceptions</a></li>
|
||
<li><a class="reference internal" href="#the-typing-module">The <code class="docutils literal notranslate"><span class="pre">typing</span></code> Module</a></li>
|
||
<li><a class="reference internal" href="#suggested-syntax-for-python-2-7-and-straddling-code">Suggested syntax for Python 2.7 and straddling code</a></li>
|
||
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a><ul>
|
||
<li><a class="reference internal" href="#which-brackets-for-generic-type-parameters">Which brackets for generic type parameters?</a></li>
|
||
<li><a class="reference internal" href="#what-about-existing-uses-of-annotations">What about existing uses of annotations?</a></li>
|
||
<li><a class="reference internal" href="#the-problem-of-forward-declarations">The problem of forward declarations</a></li>
|
||
<li><a class="reference internal" href="#the-double-colon">The double colon</a></li>
|
||
<li><a class="reference internal" href="#other-forms-of-new-syntax">Other forms of new syntax</a></li>
|
||
<li><a class="reference internal" href="#other-backwards-compatible-conventions">Other backwards compatible conventions</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#pep-development-process">PEP Development Process</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></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><a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a> introduced syntax for function annotations, but the semantics
|
||
were deliberately left undefined. There has now been enough 3rd party
|
||
usage for static type analysis that the community would benefit from
|
||
a standard vocabulary and baseline tools within the standard library.</p>
|
||
<p>This PEP introduces a provisional module to provide these standard
|
||
definitions and tools, along with some conventions for situations
|
||
where annotations are not available.</p>
|
||
<p>Note that this PEP still explicitly does NOT prevent other uses of
|
||
annotations, nor does it require (or forbid) any particular processing
|
||
of annotations, even when they conform to this specification. It
|
||
simply enables better coordination, as <a class="pep reference internal" href="../pep-0333/" title="PEP 333 – Python Web Server Gateway Interface v1.0">PEP 333</a> did for web frameworks.</p>
|
||
<p>For example, here is a simple function whose argument and return type
|
||
are declared in the annotations:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">greeting</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s1">'Hello '</span> <span class="o">+</span> <span class="n">name</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>While these annotations are available at runtime through the usual
|
||
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute, <em>no type checking happens at runtime</em>.
|
||
Instead, the proposal assumes the existence of a separate off-line
|
||
type checker which users can run over their source code voluntarily.
|
||
Essentially, such a type checker acts as a very powerful linter.
|
||
(While it would of course be possible for individual users to employ
|
||
a similar checker at run time for Design By Contract enforcement or
|
||
JIT optimization, those tools are not yet as mature.)</p>
|
||
<p>The proposal is strongly inspired by <a class="reference external" href="http://mypy-lang.org">mypy</a>. For example, the
|
||
type “sequence of integers” can be written as <code class="docutils literal notranslate"><span class="pre">Sequence[int]</span></code>. The
|
||
square brackets mean that no new syntax needs to be added to the
|
||
language. The example here uses a custom type <code class="docutils literal notranslate"><span class="pre">Sequence</span></code>, imported
|
||
from a pure-Python module <code class="docutils literal notranslate"><span class="pre">typing</span></code>. The <code class="docutils literal notranslate"><span class="pre">Sequence[int]</span></code> notation
|
||
works at runtime by implementing <code class="docutils literal notranslate"><span class="pre">__getitem__()</span></code> in the metaclass
|
||
(but its significance is primarily to an offline type checker).</p>
|
||
<p>The type system supports unions, generic types, and a special type
|
||
named <code class="docutils literal notranslate"><span class="pre">Any</span></code> which is consistent with (i.e. assignable to and from) all
|
||
types. This latter feature is taken from the idea of gradual typing.
|
||
Gradual typing and the full type system are explained in <a class="pep reference internal" href="../pep-0483/" title="PEP 483 – The Theory of Type Hints">PEP 483</a>.</p>
|
||
<p>Other approaches from which we have borrowed or to which ours can be
|
||
compared and contrasted are described in <a class="pep reference internal" href="../pep-0482/" title="PEP 482 – Literature Overview for Type Hints">PEP 482</a>.</p>
|
||
</section>
|
||
<section id="rationale-and-goals">
|
||
<h2><a class="toc-backref" href="#rationale-and-goals" role="doc-backlink">Rationale and Goals</a></h2>
|
||
<p><a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a> added support for arbitrary annotations on parts of a
|
||
function definition. Although no meaning was assigned to annotations
|
||
then, there has always been an <a class="reference external" href="https://www.artima.com/weblogs/viewpost.jsp?thread=85551">implicit goal to use them for type
|
||
hinting</a>, which is listed as the first possible use case
|
||
in said PEP.</p>
|
||
<p>This PEP aims to provide a standard syntax for type annotations,
|
||
opening up Python code to easier static analysis and refactoring,
|
||
potential runtime type checking, and (perhaps, in some contexts)
|
||
code generation utilizing type information.</p>
|
||
<p>Of these goals, static analysis is the most important. This includes
|
||
support for off-line type checkers such as mypy, as well as providing
|
||
a standard notation that can be used by IDEs for code completion and
|
||
refactoring.</p>
|
||
<section id="non-goals">
|
||
<h3><a class="toc-backref" href="#non-goals" role="doc-backlink">Non-goals</a></h3>
|
||
<p>While the proposed typing module will contain some building blocks for
|
||
runtime type checking – in particular the <code class="docutils literal notranslate"><span class="pre">get_type_hints()</span></code>
|
||
function – third party packages would have to be developed to
|
||
implement specific runtime type checking functionality, for example
|
||
using decorators or metaclasses. Using type hints for performance
|
||
optimizations is left as an exercise for the reader.</p>
|
||
<p>It should also be emphasized that <strong>Python will remain a dynamically
|
||
typed language, and the authors have no desire to ever make type hints
|
||
mandatory, even by convention.</strong></p>
|
||
</section>
|
||
</section>
|
||
<section id="the-meaning-of-annotations">
|
||
<h2><a class="toc-backref" href="#the-meaning-of-annotations" role="doc-backlink">The meaning of annotations</a></h2>
|
||
<p>Any function without annotations should be treated as having the most
|
||
general type possible, or ignored, by any type checker. Functions
|
||
with the <code class="docutils literal notranslate"><span class="pre">@no_type_check</span></code> decorator should be treated as having
|
||
no annotations.</p>
|
||
<p>It is recommended but not required that checked functions have
|
||
annotations for all arguments and the return type. For a checked
|
||
function, the default annotation for arguments and for the return type
|
||
is <code class="docutils literal notranslate"><span class="pre">Any</span></code>. An exception is the first argument of instance and
|
||
class methods. If it is not annotated, then it is assumed to have the
|
||
type of the containing class for instance methods, and a type object
|
||
type corresponding to the containing class object for class methods.
|
||
For example, in class <code class="docutils literal notranslate"><span class="pre">A</span></code> the first argument of an instance method
|
||
has the implicit type <code class="docutils literal notranslate"><span class="pre">A</span></code>. In a class method, the precise type of
|
||
the first argument cannot be represented using the available type
|
||
notation.</p>
|
||
<p>(Note that the return type of <code class="docutils literal notranslate"><span class="pre">__init__</span></code> ought to be annotated with
|
||
<code class="docutils literal notranslate"><span class="pre">-></span> <span class="pre">None</span></code>. The reason for this is subtle. If <code class="docutils literal notranslate"><span class="pre">__init__</span></code> assumed
|
||
a return annotation of <code class="docutils literal notranslate"><span class="pre">-></span> <span class="pre">None</span></code>, would that mean that an
|
||
argument-less, un-annotated <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method should still be
|
||
type-checked? Rather than leaving this ambiguous or introducing an
|
||
exception to the exception, we simply say that <code class="docutils literal notranslate"><span class="pre">__init__</span></code> ought to
|
||
have a return annotation; the default behavior is thus the same as for
|
||
other methods.)</p>
|
||
<p>A type checker is expected to check the body of a checked function for
|
||
consistency with the given annotations. The annotations may also be
|
||
used to check correctness of calls appearing in other checked functions.</p>
|
||
<p>Type checkers are expected to attempt to infer as much information as
|
||
necessary. The minimum requirement is to handle the builtin
|
||
decorators <code class="docutils literal notranslate"><span class="pre">@property</span></code>, <code class="docutils literal notranslate"><span class="pre">@staticmethod</span></code> and <code class="docutils literal notranslate"><span class="pre">@classmethod</span></code>.</p>
|
||
</section>
|
||
<section id="type-definition-syntax">
|
||
<h2><a class="toc-backref" href="#type-definition-syntax" role="doc-backlink">Type Definition Syntax</a></h2>
|
||
<p>The syntax leverages <a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a>-style annotations with a number of
|
||
extensions described in sections below. In its basic form, type
|
||
hinting is used by filling function annotation slots with classes:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">greeting</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s1">'Hello '</span> <span class="o">+</span> <span class="n">name</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This states that the expected type of the <code class="docutils literal notranslate"><span class="pre">name</span></code> argument is
|
||
<code class="docutils literal notranslate"><span class="pre">str</span></code>. Analogically, the expected return type is <code class="docutils literal notranslate"><span class="pre">str</span></code>.</p>
|
||
<p>Expressions whose type is a subtype of a specific argument type are
|
||
also accepted for that argument.</p>
|
||
<section id="acceptable-type-hints">
|
||
<h3><a class="toc-backref" href="#acceptable-type-hints" role="doc-backlink">Acceptable type hints</a></h3>
|
||
<p>Type hints may be built-in classes (including those defined in
|
||
standard library or third-party extension modules), abstract base
|
||
classes, types available in the <code class="docutils literal notranslate"><span class="pre">types</span></code> module, and user-defined
|
||
classes (including those defined in the standard library or
|
||
third-party modules).</p>
|
||
<p>While annotations are normally the best format for type hints,
|
||
there are times when it is more appropriate to represent them
|
||
by a special comment, or in a separately distributed stub
|
||
file. (See below for examples.)</p>
|
||
<p>Annotations must be valid expressions that evaluate without raising
|
||
exceptions at the time the function is defined (but see below for
|
||
forward references).</p>
|
||
<p>Annotations should be kept simple or static analysis tools may not be
|
||
able to interpret the values. For example, dynamically computed types
|
||
are unlikely to be understood. (This is an
|
||
intentionally somewhat vague requirement, specific inclusions and
|
||
exclusions may be added to future versions of this PEP as warranted by
|
||
the discussion.)</p>
|
||
<p>In addition to the above, the following special constructs defined
|
||
below may be used: <code class="docutils literal notranslate"><span class="pre">None</span></code>, <code class="docutils literal notranslate"><span class="pre">Any</span></code>, <code class="docutils literal notranslate"><span class="pre">Union</span></code>, <code class="docutils literal notranslate"><span class="pre">Tuple</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">Callable</span></code>, all ABCs and stand-ins for concrete classes exported
|
||
from <code class="docutils literal notranslate"><span class="pre">typing</span></code> (e.g. <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> and <code class="docutils literal notranslate"><span class="pre">Dict</span></code>), type variables, and
|
||
type aliases.</p>
|
||
<p>All newly introduced names used to support features described in
|
||
following sections (such as <code class="docutils literal notranslate"><span class="pre">Any</span></code> and <code class="docutils literal notranslate"><span class="pre">Union</span></code>) are available in
|
||
the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module.</p>
|
||
</section>
|
||
<section id="using-none">
|
||
<h3><a class="toc-backref" href="#using-none" role="doc-backlink">Using None</a></h3>
|
||
<p>When used in a type hint, the expression <code class="docutils literal notranslate"><span class="pre">None</span></code> is considered
|
||
equivalent to <code class="docutils literal notranslate"><span class="pre">type(None)</span></code>.</p>
|
||
</section>
|
||
<section id="type-aliases">
|
||
<h3><a class="toc-backref" href="#type-aliases" role="doc-backlink">Type aliases</a></h3>
|
||
<p>Type aliases are defined by simple variable assignments:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Url</span> <span class="o">=</span> <span class="nb">str</span>
|
||
|
||
<span class="k">def</span> <span class="nf">retry</span><span class="p">(</span><span class="n">url</span><span class="p">:</span> <span class="n">Url</span><span class="p">,</span> <span class="n">retry_count</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that we recommend capitalizing alias names, since they represent
|
||
user-defined types, which (like user-defined classes) are typically
|
||
spelled that way.</p>
|
||
<p>Type aliases may be as complex as type hints in annotations –
|
||
anything that is acceptable as a type hint is acceptable in a type
|
||
alias:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Tuple</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="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">complex</span><span class="p">)</span>
|
||
<span class="n">Vector</span> <span class="o">=</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">T</span><span class="p">,</span> <span class="n">T</span><span class="p">]]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">inproduct</span><span class="p">(</span><span class="n">v</span><span class="p">:</span> <span class="n">Vector</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="nb">sum</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">v</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">dilate</span><span class="p">(</span><span class="n">v</span><span class="p">:</span> <span class="n">Vector</span><span class="p">[</span><span class="n">T</span><span class="p">],</span> <span class="n">scale</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Vector</span><span class="p">[</span><span class="n">T</span><span class="p">]:</span>
|
||
<span class="k">return</span> <span class="p">((</span><span class="n">x</span> <span class="o">*</span> <span class="n">scale</span><span class="p">,</span> <span class="n">y</span> <span class="o">*</span> <span class="n">scale</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">v</span><span class="p">)</span>
|
||
<span class="n">vec</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: Vector[float]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is equivalent to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Tuple</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="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">complex</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">inproduct</span><span class="p">(</span><span class="n">v</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">T</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="nb">sum</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">v</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">dilate</span><span class="p">(</span><span class="n">v</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">T</span><span class="p">,</span> <span class="n">T</span><span class="p">]],</span> <span class="n">scale</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">T</span><span class="p">,</span> <span class="n">T</span><span class="p">]]:</span>
|
||
<span class="k">return</span> <span class="p">((</span><span class="n">x</span> <span class="o">*</span> <span class="n">scale</span><span class="p">,</span> <span class="n">y</span> <span class="o">*</span> <span class="n">scale</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">v</span><span class="p">)</span>
|
||
<span class="n">vec</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: Iterable[Tuple[float, float]]</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="callable">
|
||
<h3><a class="toc-backref" href="#callable" role="doc-backlink">Callable</a></h3>
|
||
<p>Frameworks expecting callback functions of specific signatures might be
|
||
type hinted using <code class="docutils literal notranslate"><span class="pre">Callable[[Arg1Type,</span> <span class="pre">Arg2Type],</span> <span class="pre">ReturnType]</span></code>.
|
||
Examples:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span>
|
||
|
||
<span class="k">def</span> <span class="nf">feeder</span><span class="p">(</span><span class="n">get_next_item</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[],</span> <span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="c1"># Body</span>
|
||
|
||
<span class="k">def</span> <span class="nf">async_query</span><span class="p">(</span><span class="n">on_success</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="nb">int</span><span class="p">],</span> <span class="kc">None</span><span class="p">],</span>
|
||
<span class="n">on_error</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="nb">int</span><span class="p">,</span> <span class="ne">Exception</span><span class="p">],</span> <span class="kc">None</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="c1"># Body</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>It is possible to declare the return type of a callable without
|
||
specifying the call signature by substituting a literal ellipsis
|
||
(three dots) for the list of arguments:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">partial</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="nb">str</span><span class="p">],</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="o">-></span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
|
||
<span class="c1"># Body</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that there are no square brackets around the ellipsis. The
|
||
arguments of the callback are completely unconstrained in this case
|
||
(and keyword arguments are acceptable).</p>
|
||
<p>Since using callbacks with keyword arguments is not perceived as a
|
||
common use case, there is currently no support for specifying keyword
|
||
arguments with <code class="docutils literal notranslate"><span class="pre">Callable</span></code>. Similarly, there is no support for
|
||
specifying callback signatures with a variable number of arguments of a
|
||
specific type.</p>
|
||
<p>Because <code class="docutils literal notranslate"><span class="pre">typing.Callable</span></code> does double-duty as a replacement for
|
||
<code class="docutils literal notranslate"><span class="pre">collections.abc.Callable</span></code>, <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">typing.Callable)</span></code> is
|
||
implemented by deferring to <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">collections.abc.Callable)</span></code>.
|
||
However, <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">typing.Callable[...])</span></code> is not supported.</p>
|
||
</section>
|
||
<section id="generics">
|
||
<h3><a class="toc-backref" href="#generics" role="doc-backlink">Generics</a></h3>
|
||
<p>Since type information about objects kept in containers cannot be
|
||
statically inferred in a generic way, abstract base classes have been
|
||
extended to support subscription to denote expected types for container
|
||
elements. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Mapping</span><span class="p">,</span> <span class="n">Set</span>
|
||
|
||
<span class="k">def</span> <span class="nf">notify_by_email</span><span class="p">(</span><span class="n">employees</span><span class="p">:</span> <span class="n">Set</span><span class="p">[</span><span class="n">Employee</span><span class="p">],</span> <span class="n">overrides</span><span class="p">:</span> <span class="n">Mapping</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</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>Generics can be parameterized by using a new factory available in
|
||
<code class="docutils literal notranslate"><span class="pre">typing</span></code> called <code class="docutils literal notranslate"><span class="pre">TypeVar</span></code>. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Sequence</span><span class="p">,</span> <span class="n">TypeVar</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="c1"># Declare type variable</span>
|
||
|
||
<span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="n">l</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"># Generic function</span>
|
||
<span class="k">return</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In this case the contract is that the returned value is consistent with
|
||
the elements held by the collection.</p>
|
||
<p>A <code class="docutils literal notranslate"><span class="pre">TypeVar()</span></code> expression must always directly be assigned to a
|
||
variable (it should not be used as part of a larger expression). The
|
||
argument to <code class="docutils literal notranslate"><span class="pre">TypeVar()</span></code> must be a string equal to the variable name
|
||
to which it is assigned. Type variables must not be redefined.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">TypeVar</span></code> supports constraining parametric types to a fixed set of possible
|
||
types (note: those types cannot be parameterized by type variables). For
|
||
example, we can define a type variable that ranges over just <code class="docutils literal notranslate"><span class="pre">str</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">bytes</span></code>. By default, a type variable ranges over all possible types.
|
||
Example of constraining a type variable:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Text</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="n">Text</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">AnyStr</span><span class="p">,</span> <span class="n">y</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">x</span> <span class="o">+</span> <span class="n">y</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The function <code class="docutils literal notranslate"><span class="pre">concat</span></code> can be called with either two <code class="docutils literal notranslate"><span class="pre">str</span></code> arguments
|
||
or two <code class="docutils literal notranslate"><span class="pre">bytes</span></code> arguments, but not with a mix of <code class="docutils literal notranslate"><span class="pre">str</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes</span></code>
|
||
arguments.</p>
|
||
<p>There should be at least two constraints, if any; specifying a single
|
||
constraint is disallowed.</p>
|
||
<p>Subtypes of types constrained by a type variable should be treated
|
||
as their respective explicitly listed base types in the context of the
|
||
type variable. Consider this example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</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">x</span> <span class="o">=</span> <span class="n">concat</span><span class="p">(</span><span class="n">MyStr</span><span class="p">(</span><span class="s1">'apple'</span><span class="p">),</span> <span class="n">MyStr</span><span class="p">(</span><span class="s1">'pie'</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The call is valid but the type variable <code class="docutils literal notranslate"><span class="pre">AnyStr</span></code> will be set to
|
||
<code class="docutils literal notranslate"><span class="pre">str</span></code> and not <code class="docutils literal notranslate"><span class="pre">MyStr</span></code>. In effect, the inferred type of the return
|
||
value assigned to <code class="docutils literal notranslate"><span class="pre">x</span></code> will also be <code class="docutils literal notranslate"><span class="pre">str</span></code>.</p>
|
||
<p>Additionally, <code class="docutils literal notranslate"><span class="pre">Any</span></code> is a valid value for every type variable.
|
||
Consider the following:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">count_truthy</span><span class="p">(</span><span class="n">elements</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">])</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">elements</span> <span class="k">if</span> <span class="n">elem</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is equivalent to omitting the generic notation and just saying
|
||
<code class="docutils literal notranslate"><span class="pre">elements:</span> <span class="pre">List</span></code>.</p>
|
||
</section>
|
||
<section id="user-defined-generic-types">
|
||
<h3><a class="toc-backref" href="#user-defined-generic-types" role="doc-backlink">User-defined generic types</a></h3>
|
||
<p>You can include a <code class="docutils literal notranslate"><span class="pre">Generic</span></code> base class to define a user-defined class
|
||
as generic. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</span>
|
||
<span class="kn">from</span> <span class="nn">logging</span> <span class="kn">import</span> <span class="n">Logger</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="k">class</span> <span class="nc">LoggedVar</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="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">logger</span><span class="p">:</span> <span class="n">Logger</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">name</span> <span class="o">=</span> <span class="n">name</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logger</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
|
||
|
||
<span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new</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="bp">self</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s1">'Set '</span> <span class="o">+</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">new</span>
|
||
|
||
<span class="k">def</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="bp">self</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s1">'Get '</span> <span class="o">+</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span>
|
||
|
||
<span class="k">def</span> <span class="nf">log</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</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">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'</span><span class="si">{}</span><span class="s1">: </span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">message</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">Generic[T]</span></code> as a base class defines that the class <code class="docutils literal notranslate"><span class="pre">LoggedVar</span></code>
|
||
takes a single type parameter <code class="docutils literal notranslate"><span class="pre">T</span></code>. This also makes <code class="docutils literal notranslate"><span class="pre">T</span></code> valid as
|
||
a type within the class body.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">Generic</span></code> base class uses a metaclass that defines <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code>
|
||
so that <code class="docutils literal notranslate"><span class="pre">LoggedVar[t]</span></code> is valid as a type:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Iterable</span>
|
||
|
||
<span class="k">def</span> <span class="nf">zero_all_vars</span><span class="p">(</span><span class="nb">vars</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">LoggedVar</span><span class="p">[</span><span class="nb">int</span><span class="p">]])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">var</span> <span class="ow">in</span> <span class="nb">vars</span><span class="p">:</span>
|
||
<span class="n">var</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A generic type can have any number of type variables, and type variables
|
||
may be constrained. This is valid:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T'</span><span class="p">)</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">class</span> <span class="nc">Pair</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>
|
||
</pre></div>
|
||
</div>
|
||
<p>Each type variable argument to <code class="docutils literal notranslate"><span class="pre">Generic</span></code> must be distinct. This is
|
||
thus invalid:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T'</span><span class="p">)</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Pair</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">T</span><span class="p">]):</span> <span class="c1"># INVALID</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">Generic[T]</span></code> base class is redundant in simple cases where you
|
||
subclass some other generic class and specify type variables for its
|
||
parameters:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Iterator</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="k">class</span> <span class="nc">MyIter</span><span class="p">(</span><span class="n">Iterator</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>That class definition is equivalent to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyIter</span><span class="p">(</span><span class="n">Iterator</span><span class="p">[</span><span class="n">T</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>
|
||
</pre></div>
|
||
</div>
|
||
<p>You can use multiple inheritance with <code class="docutils literal notranslate"><span class="pre">Generic</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</span><span class="p">,</span> <span class="n">Sized</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Container</span><span class="p">,</span> <span class="n">Tuple</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="k">class</span> <span class="nc">LinkedList</span><span class="p">(</span><span class="n">Sized</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">K</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'K'</span><span class="p">)</span>
|
||
<span class="n">V</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'V'</span><span class="p">)</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyMapping</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">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]],</span>
|
||
<span class="n">Container</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]],</span>
|
||
<span class="n">Generic</span><span class="p">[</span><span class="n">K</span><span class="p">,</span> <span class="n">V</span><span class="p">]):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Subclassing a generic class without specifying type parameters assumes
|
||
<code class="docutils literal notranslate"><span class="pre">Any</span></code> for each position. In the following example, <code class="docutils literal notranslate"><span class="pre">MyIterable</span></code>
|
||
is not generic but implicitly inherits from <code class="docutils literal notranslate"><span class="pre">Iterable[Any]</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Iterable</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyIterable</span><span class="p">(</span><span class="n">Iterable</span><span class="p">):</span> <span class="c1"># Same as Iterable[Any]</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Generic metaclasses are not supported.</p>
|
||
</section>
|
||
<section id="scoping-rules-for-type-variables">
|
||
<h3><a class="toc-backref" href="#scoping-rules-for-type-variables" role="doc-backlink">Scoping rules for type variables</a></h3>
|
||
<p>Type variables follow normal name resolution rules.
|
||
However, there are some special cases in the static typechecking context:</p>
|
||
<ul>
|
||
<li>A type variable used in a generic function could be inferred to represent
|
||
different types in the same code block. Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</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="k">def</span> <span class="nf">fun_1</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># T here</span>
|
||
<span class="k">def</span> <span class="nf">fun_2</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># and here could be different</span>
|
||
|
||
<span class="n">fun_1</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># This is OK, T is inferred to be int</span>
|
||
<span class="n">fun_2</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span> <span class="c1"># This is also OK, now T is str</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>A type variable used in a method of a generic class that coincides
|
||
with one of the variables that parameterize this class is always bound
|
||
to that variable. Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</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="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
|
||
<span class="k">def</span> <span class="nf">meth_1</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># T here</span>
|
||
<span class="k">def</span> <span class="nf">meth_2</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># and here are always the same</span>
|
||
|
||
<span class="n">a</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span> <span class="c1"># type: MyClass[int]</span>
|
||
<span class="n">a</span><span class="o">.</span><span class="n">meth_1</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># OK</span>
|
||
<span class="n">a</span><span class="o">.</span><span class="n">meth_2</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span> <span class="c1"># This is an error!</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>A type variable used in a method that does not match any of the variables
|
||
that parameterize the class makes this method a generic function in that
|
||
variable:<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">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">class</span> <span class="nc">Foo</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">T</span><span class="p">]):</span>
|
||
<span class="k">def</span> <span class="nf">method</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">y</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="o">...</span>
|
||
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">Foo</span><span class="p">()</span> <span class="c1"># type: Foo[int]</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">method</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s2">"abc"</span><span class="p">)</span> <span class="c1"># inferred type of y is str</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>Unbound type variables should not appear in the bodies of generic functions,
|
||
or in the class bodies apart from method definitions:<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">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="nf">a_fun</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="c1"># this is OK</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: List[T]</span>
|
||
<span class="c1"># but below is an error!</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: List[S]</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Bar</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"># this is also an error</span>
|
||
<span class="n">an_attr</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: List[S]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">do_something</span><span class="p">(</span><span class="n">x</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="c1"># this is OK though</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>A generic class definition that appears inside a generic function
|
||
should not use type variables that parameterize the generic function:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>
|
||
|
||
<span class="k">def</span> <span class="nf">a_fun</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
|
||
<span class="c1"># This is OK</span>
|
||
<span class="n">a_list</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: List[T]</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="c1"># This is however illegal</span>
|
||
<span class="k">class</span> <span class="nc">MyGeneric</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>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>A generic class nested in another generic class cannot use same type
|
||
variables. The scope of the type variables of the outer class
|
||
doesn’t cover the inner one:<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">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">class</span> <span class="nc">Outer</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">class</span> <span class="nc">Bad</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="c1"># Error</span>
|
||
<span class="o">...</span>
|
||
<span class="k">class</span> <span class="nc">AlsoBad</span><span class="p">:</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># type: List[T] # Also an error</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Inner</span><span class="p">(</span><span class="n">Iterable</span><span class="p">[</span><span class="n">S</span><span class="p">]):</span> <span class="c1"># OK</span>
|
||
<span class="o">...</span>
|
||
<span class="n">attr</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># type: Inner[T] # Also OK</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
<section id="instantiating-generic-classes-and-type-erasure">
|
||
<h3><a class="toc-backref" href="#instantiating-generic-classes-and-type-erasure" role="doc-backlink">Instantiating generic classes and type erasure</a></h3>
|
||
<p>User-defined generic classes can be instantiated. Suppose we write
|
||
a <code class="docutils literal notranslate"><span class="pre">Node</span></code> class inheriting from <code class="docutils literal notranslate"><span class="pre">Generic[T]</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</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="k">class</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>
|
||
</pre></div>
|
||
</div>
|
||
<p>To create <code class="docutils literal notranslate"><span class="pre">Node</span></code> instances you call <code class="docutils literal notranslate"><span class="pre">Node()</span></code> just as for a regular
|
||
class. At runtime the type (class) of the instance will be <code class="docutils literal notranslate"><span class="pre">Node</span></code>.
|
||
But what type does it have to the type checker? The answer depends on
|
||
how much information is available in the call. If the constructor
|
||
(<code class="docutils literal notranslate"><span class="pre">__init__</span></code> or <code class="docutils literal notranslate"><span class="pre">__new__</span></code>) uses <code class="docutils literal notranslate"><span class="pre">T</span></code> in its signature, and a
|
||
corresponding argument value is passed, the type of the corresponding
|
||
argument(s) is substituted. Otherwise, <code class="docutils literal notranslate"><span class="pre">Any</span></code> is assumed. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</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="k">class</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="n">x</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># type: T # Instance attribute (see below)</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">label</span><span class="p">:</span> <span class="n">T</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span> <span class="c1"># Inferred type is Node[str]</span>
|
||
<span class="n">y</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1"># Inferred type is Node[int]</span>
|
||
<span class="n">z</span> <span class="o">=</span> <span class="n">Node</span><span class="p">()</span> <span class="c1"># Inferred type is Node[Any]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In case the inferred type uses <code class="docutils literal notranslate"><span class="pre">[Any]</span></code> but the intended type is more
|
||
specific, you can use a type comment (see below) to force the type of
|
||
the variable, e.g.:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># (continued from previous example)</span>
|
||
<span class="n">a</span> <span class="o">=</span> <span class="n">Node</span><span class="p">()</span> <span class="c1"># type: Node[int]</span>
|
||
<span class="n">b</span> <span class="o">=</span> <span class="n">Node</span><span class="p">()</span> <span class="c1"># type: Node[str]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Alternatively, you can instantiate a specific concrete type, e.g.:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># (continued from previous example)</span>
|
||
<span class="n">p</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">q</span> <span class="o">=</span> <span class="n">Node</span><span class="p">[</span><span class="nb">str</span><span class="p">]()</span>
|
||
<span class="n">r</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="s1">''</span><span class="p">)</span> <span class="c1"># Error</span>
|
||
<span class="n">s</span> <span class="o">=</span> <span class="n">Node</span><span class="p">[</span><span class="nb">str</span><span class="p">](</span><span class="mi">0</span><span class="p">)</span> <span class="c1"># Error</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that the runtime type (class) of <code class="docutils literal notranslate"><span class="pre">p</span></code> and <code class="docutils literal notranslate"><span class="pre">q</span></code> is still just <code class="docutils literal notranslate"><span class="pre">Node</span></code>
|
||
– <code class="docutils literal notranslate"><span class="pre">Node[int]</span></code> and <code class="docutils literal notranslate"><span class="pre">Node[str]</span></code> are distinguishable class objects, but
|
||
the runtime class of the objects created by instantiating them doesn’t
|
||
record the distinction. This behavior is called “type erasure”; it is
|
||
common practice in languages with generics (e.g. Java, TypeScript).</p>
|
||
<p>Using generic classes (parameterized or not) to access attributes will result
|
||
in type check failure. Outside the class definition body, a class attribute
|
||
cannot be assigned, and can only be looked up by accessing it through a
|
||
class instance that does not have an instance attribute with the same name:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># (continued from previous example)</span>
|
||
<span class="n">Node</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># Error</span>
|
||
<span class="n">Node</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span><span class="o">.</span><span class="n">x</span> <span class="c1"># Error</span>
|
||
<span class="n">Node</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># Error</span>
|
||
<span class="n">Node</span><span class="o">.</span><span class="n">x</span> <span class="c1"># Error</span>
|
||
<span class="nb">type</span><span class="p">(</span><span class="n">p</span><span class="p">)</span><span class="o">.</span><span class="n">x</span> <span class="c1"># Error</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">x</span> <span class="c1"># Ok (evaluates to None)</span>
|
||
<span class="n">Node</span><span class="p">[</span><span class="nb">int</span><span class="p">]()</span><span class="o">.</span><span class="n">x</span> <span class="c1"># Ok (evaluates to None)</span>
|
||
<span class="n">p</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># Ok, but assigning to instance attribute</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Generic versions of abstract collections like <code class="docutils literal notranslate"><span class="pre">Mapping</span></code> or <code class="docutils literal notranslate"><span class="pre">Sequence</span></code>
|
||
and generic versions of built-in classes – <code class="docutils literal notranslate"><span class="pre">List</span></code>, <code class="docutils literal notranslate"><span class="pre">Dict</span></code>, <code class="docutils literal notranslate"><span class="pre">Set</span></code>,
|
||
and <code class="docutils literal notranslate"><span class="pre">FrozenSet</span></code> – cannot be instantiated. However, concrete user-defined
|
||
subclasses thereof and generic versions of concrete collections can be
|
||
instantiated:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data</span> <span class="o">=</span> <span class="n">DefaultDict</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">]()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that one should not confuse static types and runtime classes.
|
||
The type is still erased in this case and the above expression is
|
||
just a shorthand for:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data</span> <span class="o">=</span> <span class="n">collections</span><span class="o">.</span><span class="n">defaultdict</span><span class="p">()</span> <span class="c1"># type: DefaultDict[int, bytes]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>It is not recommended to use the subscripted class (e.g. <code class="docutils literal notranslate"><span class="pre">Node[int]</span></code>)
|
||
directly in an expression – using a type alias (e.g. <code class="docutils literal notranslate"><span class="pre">IntNode</span> <span class="pre">=</span> <span class="pre">Node[int]</span></code>)
|
||
instead is preferred. (First, creating the subscripted class,
|
||
e.g. <code class="docutils literal notranslate"><span class="pre">Node[int]</span></code>, has a runtime cost. Second, using a type alias
|
||
is more readable.)</p>
|
||
</section>
|
||
<section id="arbitrary-generic-types-as-base-classes">
|
||
<h3><a class="toc-backref" href="#arbitrary-generic-types-as-base-classes" role="doc-backlink">Arbitrary generic types as base classes</a></h3>
|
||
<p><code class="docutils literal notranslate"><span class="pre">Generic[T]</span></code> is only valid as a base class – it’s not a proper type.
|
||
However, user-defined generic types such as <code class="docutils literal notranslate"><span class="pre">LinkedList[T]</span></code> from the
|
||
above example and built-in generic types and ABCs such as <code class="docutils literal notranslate"><span class="pre">List[T]</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">Iterable[T]</span></code> are valid both as types and as base classes. For
|
||
example, we can define a subclass of <code class="docutils literal notranslate"><span class="pre">Dict</span></code> that specializes type
|
||
arguments:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Node</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="k">class</span> <span class="nc">SymbolTable</span><span class="p">(</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="n">Node</span><span class="p">]]):</span>
|
||
<span class="k">def</span> <span class="nf">push</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">node</span><span class="p">:</span> <span class="n">Node</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">setdefault</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">pop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">Node</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">lookup</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">Optional</span><span class="p">[</span><span class="n">Node</span><span class="p">]:</span>
|
||
<span class="n">nodes</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">nodes</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">nodes</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="k">return</span> <span class="kc">None</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">SymbolTable</span></code> is a subclass of <code class="docutils literal notranslate"><span class="pre">dict</span></code> and a subtype of <code class="docutils literal notranslate"><span class="pre">Dict[str,</span>
|
||
<span class="pre">List[Node]]</span></code>.</p>
|
||
<p>If a generic base class has a type variable as a type argument, this
|
||
makes the defined class generic. For example, we can define a generic
|
||
<code class="docutils literal notranslate"><span class="pre">LinkedList</span></code> class that is iterable and a container:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Container</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="k">class</span> <span class="nc">LinkedList</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="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Now <code class="docutils literal notranslate"><span class="pre">LinkedList[int]</span></code> is a valid type. Note that we can use <code class="docutils literal notranslate"><span class="pre">T</span></code>
|
||
multiple times in the base class list, as long as we don’t use the
|
||
same type variable <code class="docutils literal notranslate"><span class="pre">T</span></code> multiple times within <code class="docutils literal notranslate"><span class="pre">Generic[...]</span></code>.</p>
|
||
<p>Also consider the following example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Mapping</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="k">class</span> <span class="nc">MyDict</span><span class="p">(</span><span class="n">Mapping</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">T</span><span class="p">]):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In this case MyDict has a single parameter, T.</p>
|
||
</section>
|
||
<section id="abstract-generic-types">
|
||
<h3><a class="toc-backref" href="#abstract-generic-types" role="doc-backlink">Abstract generic types</a></h3>
|
||
<p>The metaclass used by <code class="docutils literal notranslate"><span class="pre">Generic</span></code> is a subclass of <code class="docutils literal notranslate"><span class="pre">abc.ABCMeta</span></code>.
|
||
A generic class can be an ABC by including abstract methods
|
||
or properties, and generic classes can also have ABCs as base
|
||
classes without a metaclass conflict.</p>
|
||
</section>
|
||
<section id="type-variables-with-an-upper-bound">
|
||
<h3><a class="toc-backref" href="#type-variables-with-an-upper-bound" role="doc-backlink">Type variables with an upper bound</a></h3>
|
||
<p>A type variable may specify an upper bound using <code class="docutils literal notranslate"><span class="pre">bound=<type></span></code> (note:
|
||
<type> itself cannot be parameterized by type variables). This means that an
|
||
actual type substituted (explicitly or implicitly) for the type variable must
|
||
be a subtype of the boundary type. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Sized</span>
|
||
|
||
<span class="n">ST</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'ST'</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="n">Sized</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">longer</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">ST</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">ST</span><span class="p">)</span> <span class="o">-></span> <span class="n">ST</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">></span> <span class="nb">len</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="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">y</span>
|
||
|
||
<span class="n">longer</span><span class="p">([</span><span class="mi">1</span><span class="p">],</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, return type List[int]</span>
|
||
<span class="n">longer</span><span class="p">({</span><span class="mi">1</span><span class="p">},</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, return type Set[int]</span>
|
||
<span class="n">longer</span><span class="p">([</span><span class="mi">1</span><span class="p">],</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, return type Collection[int]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>An upper bound cannot be combined with type constraints (as in used
|
||
<code class="docutils literal notranslate"><span class="pre">AnyStr</span></code>, see the example earlier); type constraints cause the
|
||
inferred type to be _exactly_ one of the constraint types, while an
|
||
upper bound just requires that the actual type is a subtype of the
|
||
boundary type.</p>
|
||
</section>
|
||
<section id="covariance-and-contravariance">
|
||
<h3><a class="toc-backref" href="#covariance-and-contravariance" role="doc-backlink">Covariance and contravariance</a></h3>
|
||
<p>Consider a class <code class="docutils literal notranslate"><span class="pre">Employee</span></code> with a subclass <code class="docutils literal notranslate"><span class="pre">Manager</span></code>. Now
|
||
suppose we have a function with an argument annotated with
|
||
<code class="docutils literal notranslate"><span class="pre">List[Employee]</span></code>. Should we be allowed to call this function with a
|
||
variable of type <code class="docutils literal notranslate"><span class="pre">List[Manager]</span></code> as its argument? Many people would
|
||
answer “yes, of course” without even considering the consequences.
|
||
But unless we know more about the function, a type checker should
|
||
reject such a call: the function might append an <code class="docutils literal notranslate"><span class="pre">Employee</span></code> instance
|
||
to the list, which would violate the variable’s type in the caller.</p>
|
||
<p>It turns out such an argument acts <em>contravariantly</em>, whereas the
|
||
intuitive answer (which is correct in case the function doesn’t mutate
|
||
its argument!) requires the argument to act <em>covariantly</em>. A longer
|
||
introduction to these concepts can be found on <a class="reference external" href="https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29">Wikipedia</a> and in <a class="pep reference internal" href="../pep-0483/" title="PEP 483 – The Theory of Type Hints">PEP 483</a>; here we just show how to control
|
||
a type checker’s behavior.</p>
|
||
<p>By default generic types are considered <em>invariant</em> in all type variables,
|
||
which means that values for variables annotated with types like
|
||
<code class="docutils literal notranslate"><span class="pre">List[Employee]</span></code> must exactly match the type annotation – no subclasses or
|
||
superclasses of the type parameter (in this example <code class="docutils literal notranslate"><span class="pre">Employee</span></code>) are
|
||
allowed.</p>
|
||
<p>To facilitate the declaration of container types where covariant or
|
||
contravariant type checking is acceptable, type variables accept keyword
|
||
arguments <code class="docutils literal notranslate"><span class="pre">covariant=True</span></code> or <code class="docutils literal notranslate"><span class="pre">contravariant=True</span></code>. At most one of these
|
||
may be passed. Generic types defined with such variables are considered
|
||
covariant or contravariant in the corresponding variable. By convention,
|
||
it is recommended to use names ending in <code class="docutils literal notranslate"><span class="pre">_co</span></code> for type variables
|
||
defined with <code class="docutils literal notranslate"><span class="pre">covariant=True</span></code> and names ending in <code class="docutils literal notranslate"><span class="pre">_contra</span></code> for that
|
||
defined with <code class="docutils literal notranslate"><span class="pre">contravariant=True</span></code>.</p>
|
||
<p>A typical example involves defining an immutable (or read-only)
|
||
container class:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Generic</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Iterator</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="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="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">items</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T_co</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="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Iterator</span><span class="p">[</span><span class="n">T_co</span><span class="p">]:</span> <span class="o">...</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Employee</span><span class="p">:</span> <span class="o">...</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Manager</span><span class="p">(</span><span class="n">Employee</span><span class="p">):</span> <span class="o">...</span>
|
||
|
||
<span class="k">def</span> <span class="nf">dump_employees</span><span class="p">(</span><span class="n">emps</span><span class="p">:</span> <span class="n">ImmutableList</span><span class="p">[</span><span class="n">Employee</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">emp</span> <span class="ow">in</span> <span class="n">emps</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">mgrs</span> <span class="o">=</span> <span class="n">ImmutableList</span><span class="p">([</span><span class="n">Manager</span><span class="p">()])</span> <span class="c1"># type: ImmutableList[Manager]</span>
|
||
<span class="n">dump_employees</span><span class="p">(</span><span class="n">mgrs</span><span class="p">)</span> <span class="c1"># OK</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The read-only collection classes in <code class="docutils literal notranslate"><span class="pre">typing</span></code> are all declared
|
||
covariant in their type variable (e.g. <code class="docutils literal notranslate"><span class="pre">Mapping</span></code> and <code class="docutils literal notranslate"><span class="pre">Sequence</span></code>). The
|
||
mutable collection classes (e.g. <code class="docutils literal notranslate"><span class="pre">MutableMapping</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">MutableSequence</span></code>) are declared invariant. The one example of
|
||
a contravariant type is the <code class="docutils literal notranslate"><span class="pre">Generator</span></code> type, which is contravariant
|
||
in the <code class="docutils literal notranslate"><span class="pre">send()</span></code> argument type (see below).</p>
|
||
<p>Note: Covariance or contravariance is <em>not</em> a property of a type variable,
|
||
but a property of a generic class defined using this variable.
|
||
Variance is only applicable to generic types; generic functions
|
||
do not have this property. The latter should be defined using only
|
||
type variables without <code class="docutils literal notranslate"><span class="pre">covariant</span></code> or <code class="docutils literal notranslate"><span class="pre">contravariant</span></code> keyword arguments.
|
||
For example, the following example is
|
||
fine:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Employee</span><span class="p">:</span> <span class="o">...</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Manager</span><span class="p">(</span><span class="n">Employee</span><span class="p">):</span> <span class="o">...</span>
|
||
|
||
<span class="n">E</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'E'</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="n">Employee</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">dump_employee</span><span class="p">(</span><span class="n">e</span><span class="p">:</span> <span class="n">E</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span>
|
||
|
||
<span class="n">dump_employee</span><span class="p">(</span><span class="n">Manager</span><span class="p">())</span> <span class="c1"># OK</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>while the following is prohibited:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">B_co</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'B_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">def</span> <span class="nf">bad_func</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">B_co</span><span class="p">)</span> <span class="o">-></span> <span class="n">B_co</span><span class="p">:</span> <span class="c1"># Flagged as error by a type checker</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="the-numeric-tower">
|
||
<h3><a class="toc-backref" href="#the-numeric-tower" role="doc-backlink">The numeric tower</a></h3>
|
||
<p><a class="pep reference internal" href="../pep-3141/" title="PEP 3141 – A Type Hierarchy for Numbers">PEP 3141</a> defines Python’s numeric tower, and the stdlib module
|
||
<code class="docutils literal notranslate"><span class="pre">numbers</span></code> implements the corresponding ABCs (<code class="docutils literal notranslate"><span class="pre">Number</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">Complex</span></code>, <code class="docutils literal notranslate"><span class="pre">Real</span></code>, <code class="docutils literal notranslate"><span class="pre">Rational</span></code> and <code class="docutils literal notranslate"><span class="pre">Integral</span></code>). There are some
|
||
issues with these ABCs, but the built-in concrete numeric classes
|
||
<code class="docutils literal notranslate"><span class="pre">complex</span></code>, <code class="docutils literal notranslate"><span class="pre">float</span></code> and <code class="docutils literal notranslate"><span class="pre">int</span></code> are ubiquitous (especially the
|
||
latter two :-).</p>
|
||
<p>Rather than requiring that users write <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">numbers</span></code> and then use
|
||
<code class="docutils literal notranslate"><span class="pre">numbers.Float</span></code> etc., this PEP proposes a straightforward shortcut
|
||
that is almost as effective: when an argument is annotated as having
|
||
type <code class="docutils literal notranslate"><span class="pre">float</span></code>, an argument of type <code class="docutils literal notranslate"><span class="pre">int</span></code> is acceptable; similar,
|
||
for an argument annotated as having type <code class="docutils literal notranslate"><span class="pre">complex</span></code>, arguments of
|
||
type <code class="docutils literal notranslate"><span class="pre">float</span></code> or <code class="docutils literal notranslate"><span class="pre">int</span></code> are acceptable. This does not handle
|
||
classes implementing the corresponding ABCs or the
|
||
<code class="docutils literal notranslate"><span class="pre">fractions.Fraction</span></code> class, but we believe those use cases are
|
||
exceedingly rare.</p>
|
||
</section>
|
||
<section id="forward-references">
|
||
<h3><a class="toc-backref" href="#forward-references" role="doc-backlink">Forward references</a></h3>
|
||
<p>When a type hint contains names that have not been defined yet, that
|
||
definition may be expressed as a string literal, to be resolved later.</p>
|
||
<p>A situation where this occurs commonly is the definition of a
|
||
container class, where the class being defined occurs in the signature
|
||
of some of the methods. For example, the following code (the start of
|
||
a simple binary tree implementation) does not work:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Tree</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">left</span><span class="p">:</span> <span class="n">Tree</span><span class="p">,</span> <span class="n">right</span><span class="p">:</span> <span class="n">Tree</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">left</span> <span class="o">=</span> <span class="n">left</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">right</span> <span class="o">=</span> <span class="n">right</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>To address this, we write:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Tree</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">left</span><span class="p">:</span> <span class="s1">'Tree'</span><span class="p">,</span> <span class="n">right</span><span class="p">:</span> <span class="s1">'Tree'</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">left</span> <span class="o">=</span> <span class="n">left</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">right</span> <span class="o">=</span> <span class="n">right</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The string literal should contain a valid Python expression (i.e.,
|
||
<code class="docutils literal notranslate"><span class="pre">compile(lit,</span> <span class="pre">'',</span> <span class="pre">'eval')</span></code> should be a valid code object) and it
|
||
should evaluate without errors once the module has been fully loaded.
|
||
The local and global namespace in which it is evaluated should be the
|
||
same namespaces in which default arguments to the same function would
|
||
be evaluated.</p>
|
||
<p>Moreover, the expression should be parseable as a valid type hint, i.e.,
|
||
it is constrained by the rules from the section <a class="reference internal" href="#acceptable-type-hints">Acceptable type hints</a>
|
||
above.</p>
|
||
<p>It is allowable to use string literals as <em>part</em> of a type hint, for
|
||
example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Tree</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
<span class="k">def</span> <span class="nf">leaves</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="s1">'Tree'</span><span class="p">]:</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A common use for forward references is when e.g. Django models are
|
||
needed in the signatures. Typically, each model is in a separate
|
||
file, and has methods taking arguments whose type involves other models.
|
||
Because of the way circular imports work in Python, it is often not
|
||
possible to import all the needed models directly:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># File models/a.py</span>
|
||
<span class="kn">from</span> <span class="nn">models.b</span> <span class="kn">import</span> <span class="n">B</span>
|
||
<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="n">B</span><span class="p">):</span> <span class="o">...</span>
|
||
|
||
<span class="c1"># File models/b.py</span>
|
||
<span class="kn">from</span> <span class="nn">models.a</span> <span class="kn">import</span> <span class="n">A</span>
|
||
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="nf">bar</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="n">A</span><span class="p">):</span> <span class="o">...</span>
|
||
|
||
<span class="c1"># File main.py</span>
|
||
<span class="kn">from</span> <span class="nn">models.a</span> <span class="kn">import</span> <span class="n">A</span>
|
||
<span class="kn">from</span> <span class="nn">models.b</span> <span class="kn">import</span> <span class="n">B</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Assuming main is imported first, this will fail with an ImportError at
|
||
the line <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">models.a</span> <span class="pre">import</span> <span class="pre">A</span></code> in models/b.py, which is being
|
||
imported from models/a.py before a has defined class A. The solution
|
||
is to switch to module-only imports and reference the models by their
|
||
_module_._class_ name:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># File models/a.py</span>
|
||
<span class="kn">from</span> <span class="nn">models</span> <span class="kn">import</span> <span class="n">b</span>
|
||
<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="s1">'b.B'</span><span class="p">):</span> <span class="o">...</span>
|
||
|
||
<span class="c1"># File models/b.py</span>
|
||
<span class="kn">from</span> <span class="nn">models</span> <span class="kn">import</span> <span class="n">a</span>
|
||
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="nf">bar</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="s1">'a.A'</span><span class="p">):</span> <span class="o">...</span>
|
||
|
||
<span class="c1"># File main.py</span>
|
||
<span class="kn">from</span> <span class="nn">models.a</span> <span class="kn">import</span> <span class="n">A</span>
|
||
<span class="kn">from</span> <span class="nn">models.b</span> <span class="kn">import</span> <span class="n">B</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="union-types">
|
||
<h3><a class="toc-backref" href="#union-types" role="doc-backlink">Union types</a></h3>
|
||
<p>Since accepting a small, limited set of expected types for a single
|
||
argument is common, there is a new special factory called <code class="docutils literal notranslate"><span class="pre">Union</span></code>.
|
||
Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Union</span>
|
||
|
||
<span class="k">def</span> <span class="nf">handle_employees</span><span class="p">(</span><span class="n">e</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">Employee</span><span class="p">,</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">Employee</span><span class="p">]])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Employee</span><span class="p">):</span>
|
||
<span class="n">e</span> <span class="o">=</span> <span class="p">[</span><span class="n">e</span><span class="p">]</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A type factored by <code class="docutils literal notranslate"><span class="pre">Union[T1,</span> <span class="pre">T2,</span> <span class="pre">...]</span></code> is a supertype
|
||
of all types <code class="docutils literal notranslate"><span class="pre">T1</span></code>, <code class="docutils literal notranslate"><span class="pre">T2</span></code>, etc., so that a value that
|
||
is a member of one of these types is acceptable for an argument
|
||
annotated by <code class="docutils literal notranslate"><span class="pre">Union[T1,</span> <span class="pre">T2,</span> <span class="pre">...]</span></code>.</p>
|
||
<p>One common case of union types are <em>optional</em> types. By default,
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code> is an invalid value for any type, unless a default value of
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code> has been provided in the function definition. Examples:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">handle_employee</span><span class="p">(</span><span class="n">e</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">Employee</span><span class="p">,</span> <span class="kc">None</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>As a shorthand for <code class="docutils literal notranslate"><span class="pre">Union[T1,</span> <span class="pre">None]</span></code> you can write <code class="docutils literal notranslate"><span class="pre">Optional[T1]</span></code>;
|
||
for example, the above is equivalent to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span>
|
||
|
||
<span class="k">def</span> <span class="nf">handle_employee</span><span class="p">(</span><span class="n">e</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Employee</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>A past version of this PEP allowed type checkers to assume an optional
|
||
type when the default value is <code class="docutils literal notranslate"><span class="pre">None</span></code>, as in this code:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">handle_employee</span><span class="p">(</span><span class="n">e</span><span class="p">:</span> <span class="n">Employee</span> <span class="o">=</span> <span class="kc">None</span><span class="p">):</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This would have been treated as equivalent to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">handle_employee</span><span class="p">(</span><span class="n">e</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Employee</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</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>This is no longer the recommended behavior. Type checkers should move
|
||
towards requiring the optional type to be made explicit.</p>
|
||
</section>
|
||
<section id="support-for-singleton-types-in-unions">
|
||
<h3><a class="toc-backref" href="#support-for-singleton-types-in-unions" role="doc-backlink">Support for singleton types in unions</a></h3>
|
||
<p>A singleton instance is frequently used to mark some special condition,
|
||
in particular in situations where <code class="docutils literal notranslate"><span class="pre">None</span></code> is also a valid value
|
||
for a variable. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">_empty</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">_empty</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="n">_empty</span><span class="p">:</span> <span class="c1"># default argument value</span>
|
||
<span class="k">return</span> <span class="mi">0</span>
|
||
<span class="k">elif</span> <span class="n">x</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># argument was provided and it's None</span>
|
||
<span class="k">return</span> <span class="mi">1</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>To allow precise typing in such situations, the user should use
|
||
the <code class="docutils literal notranslate"><span class="pre">Union</span></code> type in conjunction with the <code class="docutils literal notranslate"><span class="pre">enum.Enum</span></code> class provided
|
||
by the standard library, so that type errors can be caught statically:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Union</span>
|
||
<span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Empty</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">token</span> <span class="o">=</span> <span class="mi">0</span>
|
||
<span class="n">_empty</span> <span class="o">=</span> <span class="n">Empty</span><span class="o">.</span><span class="n">token</span>
|
||
|
||
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="n">Empty</span><span class="p">]</span> <span class="o">=</span> <span class="n">_empty</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
|
||
|
||
<span class="n">boom</span> <span class="o">=</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">42</span> <span class="c1"># This fails type check</span>
|
||
|
||
<span class="k">if</span> <span class="n">x</span> <span class="ow">is</span> <span class="n">_empty</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="mi">0</span>
|
||
<span class="k">elif</span> <span class="n">x</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="mi">1</span>
|
||
<span class="k">else</span><span class="p">:</span> <span class="c1"># At this point typechecker knows that x can only have type int</span>
|
||
<span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Since the subclasses of <code class="docutils literal notranslate"><span class="pre">Enum</span></code> cannot be further subclassed,
|
||
the type of variable <code class="docutils literal notranslate"><span class="pre">x</span></code> can be statically inferred in all branches
|
||
of the above example. The same approach is applicable if more than one
|
||
singleton object is needed: one can use an enumeration that has more than
|
||
one value:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Reason</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">timeout</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">error</span> <span class="o">=</span> <span class="mi">2</span>
|
||
|
||
<span class="k">def</span> <span class="nf">process</span><span class="p">(</span><span class="n">response</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="n">Reason</span><span class="p">]</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">response</span> <span class="ow">is</span> <span class="n">Reason</span><span class="o">.</span><span class="n">timeout</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s1">'TIMEOUT'</span>
|
||
<span class="k">elif</span> <span class="n">response</span> <span class="ow">is</span> <span class="n">Reason</span><span class="o">.</span><span class="n">error</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s1">'ERROR'</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># response can be only str, all other possible values exhausted</span>
|
||
<span class="k">return</span> <span class="s1">'PROCESSED: '</span> <span class="o">+</span> <span class="n">response</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="the-any-type">
|
||
<h3><a class="toc-backref" href="#the-any-type" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">Any</span></code> type</a></h3>
|
||
<p>A special kind of type is <code class="docutils literal notranslate"><span class="pre">Any</span></code>. Every type is consistent with
|
||
<code class="docutils literal notranslate"><span class="pre">Any</span></code>. It can be considered a type that has all values and all methods.
|
||
Note that <code class="docutils literal notranslate"><span class="pre">Any</span></code> and builtin type <code class="docutils literal notranslate"><span class="pre">object</span></code> are completely different.</p>
|
||
<p>When the type of a value is <code class="docutils literal notranslate"><span class="pre">object</span></code>, the type checker will reject
|
||
almost all operations on it, and assigning it to a variable (or using
|
||
it as a return value) of a more specialized type is a type error. On
|
||
the other hand, when a value has type <code class="docutils literal notranslate"><span class="pre">Any</span></code>, the type checker will
|
||
allow all operations on it, and a value of type <code class="docutils literal notranslate"><span class="pre">Any</span></code> can be assigned
|
||
to a variable (or used as a return value) of a more constrained type.</p>
|
||
<p>A function parameter without an annotation is assumed to be annotated with
|
||
<code class="docutils literal notranslate"><span class="pre">Any</span></code>. If a generic type is used without specifying type parameters,
|
||
they are assumed to be <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="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Mapping</span>
|
||
|
||
<span class="k">def</span> <span class="nf">use_map</span><span class="p">(</span><span class="n">m</span><span class="p">:</span> <span class="n">Mapping</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="c1"># Same as Mapping[Any, Any]</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This rule also applies to <code class="docutils literal notranslate"><span class="pre">Tuple</span></code>, in annotation context it is equivalent
|
||
to <code class="docutils literal notranslate"><span class="pre">Tuple[Any,</span> <span class="pre">...]</span></code> and, in turn, to <code class="docutils literal notranslate"><span class="pre">tuple</span></code>. As well, a bare
|
||
<code class="docutils literal notranslate"><span class="pre">Callable</span></code> in an annotation is equivalent to <code class="docutils literal notranslate"><span class="pre">Callable[...,</span> <span class="pre">Any]</span></code> and,
|
||
in turn, to <code class="docutils literal notranslate"><span class="pre">collections.abc.Callable</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Tuple</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Callable</span>
|
||
|
||
<span class="k">def</span> <span class="nf">check_args</span><span class="p">(</span><span class="n">args</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">check_args</span><span class="p">(())</span> <span class="c1"># OK</span>
|
||
<span class="n">check_args</span><span class="p">((</span><span class="mi">42</span><span class="p">,</span> <span class="s1">'abc'</span><span class="p">))</span> <span class="c1"># Also OK</span>
|
||
<span class="n">check_args</span><span class="p">(</span><span class="mf">3.14</span><span class="p">)</span> <span class="c1"># Flagged as error by a type checker</span>
|
||
|
||
<span class="c1"># A list of arbitrary callables is accepted by this function</span>
|
||
<span class="k">def</span> <span class="nf">apply_callbacks</span><span class="p">(</span><span class="n">cbs</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Callable</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>
|
||
</section>
|
||
<section id="the-noreturn-type">
|
||
<h3><a class="toc-backref" href="#the-noreturn-type" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> type</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">typing</span></code> module provides a special type <code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> to annotate functions
|
||
that never return normally. For example, a function that unconditionally
|
||
raises an exception:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">NoReturn</span>
|
||
|
||
<span class="k">def</span> <span class="nf">stop</span><span class="p">()</span> <span class="o">-></span> <span class="n">NoReturn</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s1">'no way'</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> annotation is used for functions such as <code class="docutils literal notranslate"><span class="pre">sys.exit</span></code>.
|
||
Static type checkers will ensure that functions annotated as returning
|
||
<code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> truly never return, either implicitly or explicitly:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
|
||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">NoReturn</span>
|
||
|
||
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="n">NoReturn</span><span class="p">:</span> <span class="c1"># Error, f(0) implicitly returns None</span>
|
||
<span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The checkers will also recognize that the code after calls to such functions
|
||
is unreachable and will behave accordingly:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># continue from first example</span>
|
||
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">x</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">x</span>
|
||
<span class="n">stop</span><span class="p">()</span>
|
||
<span class="k">return</span> <span class="s1">'whatever works'</span> <span class="c1"># Error might be not reported by some checkers</span>
|
||
<span class="c1"># that ignore errors in unreachable blocks</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> type is only valid as a return annotation of functions,
|
||
and considered an error if it appears in other positions:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">NoReturn</span>
|
||
|
||
<span class="c1"># All of the following are errors</span>
|
||
<span class="k">def</span> <span class="nf">bad1</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">NoReturn</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
<span class="n">bad2</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># type: NoReturn</span>
|
||
<span class="k">def</span> <span class="nf">bad3</span><span class="p">()</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="n">NoReturn</span><span class="p">]:</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="the-type-of-class-objects">
|
||
<h3><a class="toc-backref" href="#the-type-of-class-objects" role="doc-backlink">The type of class objects</a></h3>
|
||
<p>Sometimes you want to talk about class objects, in particular class
|
||
objects that inherit from a given class. This can be spelled as
|
||
<code class="docutils literal notranslate"><span class="pre">Type[C]</span></code> where <code class="docutils literal notranslate"><span class="pre">C</span></code> is a class. To clarify: while <code class="docutils literal notranslate"><span class="pre">C</span></code> (when
|
||
used as an annotation) refers to instances of class <code class="docutils literal notranslate"><span class="pre">C</span></code>, <code class="docutils literal notranslate"><span class="pre">Type[C]</span></code>
|
||
refers to <em>subclasses</em> of <code class="docutils literal notranslate"><span class="pre">C</span></code>. (This is a similar distinction as
|
||
between <code class="docutils literal notranslate"><span class="pre">object</span></code> and <code class="docutils literal notranslate"><span class="pre">type</span></code>.)</p>
|
||
<p>For example, suppose we have the following classes:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">User</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># Abstract base for User classes</span>
|
||
<span class="k">class</span> <span class="nc">BasicUser</span><span class="p">(</span><span class="n">User</span><span class="p">):</span> <span class="o">...</span>
|
||
<span class="k">class</span> <span class="nc">ProUser</span><span class="p">(</span><span class="n">User</span><span class="p">):</span> <span class="o">...</span>
|
||
<span class="k">class</span> <span class="nc">TeamUser</span><span class="p">(</span><span class="n">User</span><span class="p">):</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>And suppose we have a function that creates an instance of one of
|
||
these classes if you pass it a class object:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">new_user</span><span class="p">(</span><span class="n">user_class</span><span class="p">):</span>
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">user_class</span><span class="p">()</span>
|
||
<span class="c1"># (Here we could write the user object to a database)</span>
|
||
<span class="k">return</span> <span class="n">user</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Without <code class="docutils literal notranslate"><span class="pre">Type[]</span></code> the best we could do to annotate <code class="docutils literal notranslate"><span class="pre">new_user()</span></code>
|
||
would be:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">new_user</span><span class="p">(</span><span class="n">user_class</span><span class="p">:</span> <span class="nb">type</span><span class="p">)</span> <span class="o">-></span> <span class="n">User</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However using <code class="docutils literal notranslate"><span class="pre">Type[]</span></code> and a type variable with an upper bound we
|
||
can do much better:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">U</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'U'</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="n">User</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">new_user</span><span class="p">(</span><span class="n">user_class</span><span class="p">:</span> <span class="n">Type</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="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Now when we call <code class="docutils literal notranslate"><span class="pre">new_user()</span></code> with a specific subclass of <code class="docutils literal notranslate"><span class="pre">User</span></code> a
|
||
type checker will infer the correct type of the result:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">joe</span> <span class="o">=</span> <span class="n">new_user</span><span class="p">(</span><span class="n">BasicUser</span><span class="p">)</span> <span class="c1"># Inferred type is BasicUser</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The value corresponding to <code class="docutils literal notranslate"><span class="pre">Type[C]</span></code> must be an actual class object
|
||
that’s a subtype of <code class="docutils literal notranslate"><span class="pre">C</span></code>, not a special form. In other words, in the
|
||
above example calling e.g. <code class="docutils literal notranslate"><span class="pre">new_user(Union[BasicUser,</span> <span class="pre">ProUser])</span></code> is
|
||
rejected by the type checker (in addition to failing at runtime
|
||
because you can’t instantiate a union).</p>
|
||
<p>Note that it is legal to use a union of classes as the parameter for
|
||
<code class="docutils literal notranslate"><span class="pre">Type[]</span></code>, as in:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">new_non_team_user</span><span class="p">(</span><span class="n">user_class</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">BasicUser</span><span class="p">,</span> <span class="n">ProUser</span><span class="p">]]):</span>
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">new_user</span><span class="p">(</span><span class="n">user_class</span><span class="p">)</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However the actual argument passed in at runtime must still be a
|
||
concrete class object, e.g. in the above example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">new_non_team_user</span><span class="p">(</span><span class="n">ProUser</span><span class="p">)</span> <span class="c1"># OK</span>
|
||
<span class="n">new_non_team_user</span><span class="p">(</span><span class="n">TeamUser</span><span class="p">)</span> <span class="c1"># Disallowed by type checker</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">Type[Any]</span></code> is also supported (see below for its meaning).</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">Type[T]</span></code> where <code class="docutils literal notranslate"><span class="pre">T</span></code> is a type variable is allowed when annotating the
|
||
first argument of a class method (see the relevant section).</p>
|
||
<p>Any other special constructs like <code class="docutils literal notranslate"><span class="pre">Tuple</span></code> or <code class="docutils literal notranslate"><span class="pre">Callable</span></code> are not allowed
|
||
as an argument to <code class="docutils literal notranslate"><span class="pre">Type</span></code>.</p>
|
||
<p>There are some concerns with this feature: for example when
|
||
<code class="docutils literal notranslate"><span class="pre">new_user()</span></code> calls <code class="docutils literal notranslate"><span class="pre">user_class()</span></code> this implies that all subclasses
|
||
of <code class="docutils literal notranslate"><span class="pre">User</span></code> must support this in their constructor signature. However
|
||
this is not unique to <code class="docutils literal notranslate"><span class="pre">Type[]</span></code>: class methods have similar concerns.
|
||
A type checker ought to flag violations of such assumptions, but by
|
||
default constructor calls that match the constructor signature in the
|
||
indicated base class (<code class="docutils literal notranslate"><span class="pre">User</span></code> in the example above) should be
|
||
allowed. A program containing a complex or extensible class hierarchy
|
||
might also handle this by using a factory class method. A future
|
||
revision of this PEP may introduce better ways of dealing with these
|
||
concerns.</p>
|
||
<p>When <code class="docutils literal notranslate"><span class="pre">Type</span></code> is parameterized it requires exactly one parameter.
|
||
Plain <code class="docutils literal notranslate"><span class="pre">Type</span></code> without brackets is equivalent to <code class="docutils literal notranslate"><span class="pre">Type[Any]</span></code> and
|
||
this in turn is equivalent to <code class="docutils literal notranslate"><span class="pre">type</span></code> (the root of Python’s metaclass
|
||
hierarchy). This equivalence also motivates the name, <code class="docutils literal notranslate"><span class="pre">Type</span></code>, as
|
||
opposed to alternatives like <code class="docutils literal notranslate"><span class="pre">Class</span></code> or <code class="docutils literal notranslate"><span class="pre">SubType</span></code>, which were
|
||
proposed while this feature was under discussion; this is similar to
|
||
the relationship between e.g. <code class="docutils literal notranslate"><span class="pre">List</span></code> and <code class="docutils literal notranslate"><span class="pre">list</span></code>.</p>
|
||
<p>Regarding the behavior of <code class="docutils literal notranslate"><span class="pre">Type[Any]</span></code> (or <code class="docutils literal notranslate"><span class="pre">Type</span></code> or <code class="docutils literal notranslate"><span class="pre">type</span></code>),
|
||
accessing attributes of a variable with this type only provides
|
||
attributes and methods defined by <code class="docutils literal notranslate"><span class="pre">type</span></code> (for example,
|
||
<code class="docutils literal notranslate"><span class="pre">__repr__()</span></code> and <code class="docutils literal notranslate"><span class="pre">__mro__</span></code>). Such a variable can be called with
|
||
arbitrary arguments, and the return type is <code class="docutils literal notranslate"><span class="pre">Any</span></code>.</p>
|
||
<p><code class="docutils literal notranslate"><span class="pre">Type</span></code> is covariant in its parameter, because <code class="docutils literal notranslate"><span class="pre">Type[Derived]</span></code> is a
|
||
subtype of <code class="docutils literal notranslate"><span class="pre">Type[Base]</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">new_pro_user</span><span class="p">(</span><span class="n">pro_user_class</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">ProUser</span><span class="p">]):</span>
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">new_user</span><span class="p">(</span><span class="n">pro_user_class</span><span class="p">)</span> <span class="c1"># OK</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="annotating-instance-and-class-methods">
|
||
<h3><a class="toc-backref" href="#annotating-instance-and-class-methods" role="doc-backlink">Annotating instance and class methods</a></h3>
|
||
<p>In most cases the first argument of class and instance methods
|
||
does not need to be annotated, and it is assumed to have the
|
||
type of the containing class for instance methods, and a type object
|
||
type corresponding to the containing class object for class methods.
|
||
In addition, the first argument in an instance method can be annotated
|
||
with a type variable. In this case the return type may use the same
|
||
type variable, thus making that method a generic function. For example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T'</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s1">'Copyable'</span><span class="p">)</span>
|
||
<span class="k">class</span> <span class="nc">Copyable</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span>
|
||
<span class="c1"># return a copy of self</span>
|
||
|
||
<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">Copyable</span><span class="p">):</span> <span class="o">...</span>
|
||
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
|
||
<span class="n">c2</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="c1"># type here should be C</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The same applies to class methods using <code class="docutils literal notranslate"><span class="pre">Type[]</span></code> in an annotation
|
||
of the first argument:</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">bound</span><span class="o">=</span><span class="s1">'C'</span><span class="p">)</span>
|
||
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
|
||
<span class="nd">@classmethod</span>
|
||
<span class="k">def</span> <span class="nf">factory</span><span class="p">(</span><span class="bp">cls</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">T</span><span class="p">])</span> <span class="o">-></span> <span class="n">T</span><span class="p">:</span>
|
||
<span class="c1"># make a new instance of cls</span>
|
||
|
||
<span class="k">class</span> <span class="nc">D</span><span class="p">(</span><span class="n">C</span><span class="p">):</span> <span class="o">...</span>
|
||
<span class="n">d</span> <span class="o">=</span> <span class="n">D</span><span class="o">.</span><span class="n">factory</span><span class="p">()</span> <span class="c1"># type here should be D</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that some type checkers may apply restrictions on this use, such as
|
||
requiring an appropriate upper bound for the type variable used
|
||
(see examples).</p>
|
||
</section>
|
||
<section id="version-and-platform-checking">
|
||
<h3><a class="toc-backref" href="#version-and-platform-checking" role="doc-backlink">Version and platform checking</a></h3>
|
||
<p>Type checkers are expected to understand simple version and platform
|
||
checks, e.g.:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
|
||
|
||
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">>=</span> <span class="mi">3</span><span class="p">:</span>
|
||
<span class="c1"># Python 3 specific definitions</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># Python 2 specific definitions</span>
|
||
|
||
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">'win32'</span><span class="p">:</span>
|
||
<span class="c1"># Windows specific definitions</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># Posix specific definitions</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Don’t expect a checker to understand obfuscations like
|
||
<code class="docutils literal notranslate"><span class="pre">"".join(reversed(sys.platform))</span> <span class="pre">==</span> <span class="pre">"xunil"</span></code>.</p>
|
||
</section>
|
||
<section id="runtime-or-type-checking">
|
||
<h3><a class="toc-backref" href="#runtime-or-type-checking" role="doc-backlink">Runtime or type checking?</a></h3>
|
||
<p>Sometimes there’s code that must be seen by a type checker (or other
|
||
static analysis tools) but should not be executed. For such
|
||
situations the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module defines a constant,
|
||
<code class="docutils literal notranslate"><span class="pre">TYPE_CHECKING</span></code>, that is considered <code class="docutils literal notranslate"><span class="pre">True</span></code> during type checking
|
||
(or other static analysis) but <code class="docutils literal notranslate"><span class="pre">False</span></code> at runtime. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">typing</span>
|
||
|
||
<span class="k">if</span> <span class="n">typing</span><span class="o">.</span><span class="n">TYPE_CHECKING</span><span class="p">:</span>
|
||
<span class="kn">import</span> <span class="nn">expensive_mod</span>
|
||
|
||
<span class="k">def</span> <span class="nf">a_func</span><span class="p">(</span><span class="n">arg</span><span class="p">:</span> <span class="s1">'expensive_mod.SomeClass'</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="n">a_var</span> <span class="o">=</span> <span class="n">arg</span> <span class="c1"># type: expensive_mod.SomeClass</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>(Note that the type annotation must be enclosed in quotes, making it a
|
||
“forward reference”, to hide the <code class="docutils literal notranslate"><span class="pre">expensive_mod</span></code> reference from the
|
||
interpreter runtime. In the <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type</span></code> comment no quotes are needed.)</p>
|
||
<p>This approach may also be useful to handle import cycles.</p>
|
||
</section>
|
||
<section id="arbitrary-argument-lists-and-default-argument-values">
|
||
<h3><a class="toc-backref" href="#arbitrary-argument-lists-and-default-argument-values" role="doc-backlink">Arbitrary argument lists and default argument values</a></h3>
|
||
<p>Arbitrary argument lists can as well be type annotated,
|
||
so that the definition:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>is acceptable and it means that, e.g., all of the following
|
||
represent function calls with valid types of arguments:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">foo</span><span class="p">(</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">)</span>
|
||
<span class="n">foo</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
|
||
<span class="n">foo</span><span class="p">(</span><span class="s1">''</span><span class="p">,</span> <span class="n">z</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In the body of function <code class="docutils literal notranslate"><span class="pre">foo</span></code>, the type of variable <code class="docutils literal notranslate"><span class="pre">args</span></code> is
|
||
deduced as <code class="docutils literal notranslate"><span class="pre">Tuple[str,</span> <span class="pre">...]</span></code> and the type of variable <code class="docutils literal notranslate"><span class="pre">kwds</span></code>
|
||
is <code class="docutils literal notranslate"><span class="pre">Dict[str,</span> <span class="pre">int]</span></code>.</p>
|
||
<p>In stubs it may be useful to declare an argument as having a default
|
||
without specifying the actual default value. For example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">AnyStr</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">AnyStr</span> <span class="o">=</span> <span class="o">...</span><span class="p">)</span> <span class="o">-></span> <span class="n">AnyStr</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>What should the default value look like? Any of the options <code class="docutils literal notranslate"><span class="pre">""</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">b""</span></code> or <code class="docutils literal notranslate"><span class="pre">None</span></code> fails to satisfy the type constraint.</p>
|
||
<p>In such cases the default value may be specified as a literal
|
||
ellipsis, i.e. the above example is literally what you would write.</p>
|
||
</section>
|
||
<section id="positional-only-arguments">
|
||
<h3><a class="toc-backref" href="#positional-only-arguments" role="doc-backlink">Positional-only arguments</a></h3>
|
||
<p>Some functions are designed to take their arguments only positionally,
|
||
and expect their callers never to use the argument’s name to provide
|
||
that argument by keyword. All arguments with names beginning with
|
||
<code class="docutils literal notranslate"><span class="pre">__</span></code> are assumed to be positional-only, except if their names also
|
||
end with <code class="docutils literal notranslate"><span class="pre">__</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">quux</span><span class="p">(</span><span class="n">__x</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">__y__</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span>
|
||
|
||
<span class="n">quux</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">__y__</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># This call is fine.</span>
|
||
|
||
<span class="n">quux</span><span class="p">(</span><span class="n">__x</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span> <span class="c1"># This call is an error.</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="annotating-generator-functions-and-coroutines">
|
||
<h3><a class="toc-backref" href="#annotating-generator-functions-and-coroutines" role="doc-backlink">Annotating generator functions and coroutines</a></h3>
|
||
<p>The return type of generator functions can be annotated by
|
||
the generic type <code class="docutils literal notranslate"><span class="pre">Generator[yield_type,</span> <span class="pre">send_type,</span>
|
||
<span class="pre">return_type]</span></code> provided by <code class="docutils literal notranslate"><span class="pre">typing.py</span></code> module:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">echo_round</span><span class="p">()</span> <span class="o">-></span> <span class="n">Generator</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
|
||
<span class="n">res</span> <span class="o">=</span> <span class="k">yield</span>
|
||
<span class="k">while</span> <span class="n">res</span><span class="p">:</span>
|
||
<span class="n">res</span> <span class="o">=</span> <span class="k">yield</span> <span class="nb">round</span><span class="p">(</span><span class="n">res</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="s1">'OK'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Coroutines introduced in <a class="pep reference internal" href="../pep-0492/" title="PEP 492 – Coroutines with async and await syntax">PEP 492</a> are annotated with the same syntax as
|
||
ordinary functions. However, the return type annotation corresponds to the
|
||
type of <code class="docutils literal notranslate"><span class="pre">await</span></code> expression, not to the coroutine type:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">spam</span><span class="p">(</span><span class="n">ignored</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s1">'spam'</span>
|
||
|
||
<span class="k">async</span> <span class="k">def</span> <span class="nf">foo</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="n">bar</span> <span class="o">=</span> <span class="k">await</span> <span class="n">spam</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># type: str</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">typing.py</span></code> module provides a generic version of ABC
|
||
<code class="docutils literal notranslate"><span class="pre">collections.abc.Coroutine</span></code> to specify awaitables that also support
|
||
<code class="docutils literal notranslate"><span class="pre">send()</span></code> and <code class="docutils literal notranslate"><span class="pre">throw()</span></code> methods. The variance and order of type variables
|
||
correspond to those of <code class="docutils literal notranslate"><span class="pre">Generator</span></code>, namely <code class="docutils literal notranslate"><span class="pre">Coroutine[T_co,</span> <span class="pre">T_contra,</span> <span class="pre">V_co]</span></code>,
|
||
for example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Coroutine</span>
|
||
<span class="n">c</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># type: Coroutine[List[str], str, int]</span>
|
||
<span class="o">...</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">'hi'</span><span class="p">)</span> <span class="c1"># type: List[str]</span>
|
||
<span class="k">async</span> <span class="k">def</span> <span class="nf">bar</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="n">x</span> <span class="o">=</span> <span class="k">await</span> <span class="n">c</span> <span class="c1"># type: int</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The module also provides generic ABCs <code class="docutils literal notranslate"><span class="pre">Awaitable</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">AsyncIterable</span></code>, and <code class="docutils literal notranslate"><span class="pre">AsyncIterator</span></code> for situations where more precise
|
||
types cannot be specified:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">op</span><span class="p">()</span> <span class="o">-></span> <span class="n">typing</span><span class="o">.</span><span class="n">Awaitable</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
||
<span class="k">if</span> <span class="n">cond</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">spam</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">Future</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="compatibility-with-other-uses-of-function-annotations">
|
||
<h2><a class="toc-backref" href="#compatibility-with-other-uses-of-function-annotations" role="doc-backlink">Compatibility with other uses of function annotations</a></h2>
|
||
<p>A number of existing or potential use cases for function annotations
|
||
exist, which are incompatible with type hinting. These may confuse
|
||
a static type checker. However, since type hinting annotations have no
|
||
runtime behavior (other than evaluation of the annotation expression and
|
||
storing annotations in the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute of the function
|
||
object), this does not make the program incorrect – it just may cause
|
||
a type checker to emit spurious warnings or errors.</p>
|
||
<p>To mark portions of the program that should not be covered by type
|
||
hinting, you can use one or more of the following:</p>
|
||
<ul class="simple">
|
||
<li>a <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> comment;</li>
|
||
<li>a <code class="docutils literal notranslate"><span class="pre">@no_type_check</span></code> decorator on a class or function;</li>
|
||
<li>a custom class or function decorator marked with
|
||
<code class="docutils literal notranslate"><span class="pre">@no_type_check_decorator</span></code>.</li>
|
||
</ul>
|
||
<p>For more details see later sections.</p>
|
||
<p>In order for maximal compatibility with offline type checking it may
|
||
eventually be a good idea to change interfaces that rely on annotations
|
||
to switch to a different mechanism, for example a decorator. In Python
|
||
3.5 there is no pressure to do this, however. See also the longer
|
||
discussion under <a class="reference internal" href="#rejected-alternatives">Rejected alternatives</a> below.</p>
|
||
</section>
|
||
<section id="type-comments">
|
||
<h2><a class="toc-backref" href="#type-comments" role="doc-backlink">Type comments</a></h2>
|
||
<p>No first-class syntax support for explicitly marking variables as being
|
||
of a specific type is added by this PEP. To help with type inference in
|
||
complex cases, a comment of the following format may be used:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># type: List[Employee]</span>
|
||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[],</span> <span class="p">[]</span> <span class="c1"># type: List[int], List[int], List[str]</span>
|
||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[],</span> <span class="p">[]</span> <span class="c1"># type: (List[int], List[int], List[str])</span>
|
||
<span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="o">*</span><span class="n">c</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># type: float, float, List[float]</span>
|
||
<span class="n">x</span> <span class="o">=</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"># type: List[int]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Type comments should be put on the last line of the statement that
|
||
contains the variable definition. They can also be placed on
|
||
<code class="docutils literal notranslate"><span class="pre">with</span></code> statements and <code class="docutils literal notranslate"><span class="pre">for</span></code> statements, right after the colon.</p>
|
||
<p>Examples of type comments on <code class="docutils literal notranslate"><span class="pre">with</span></code> and <code class="docutils literal notranslate"><span class="pre">for</span></code> statements:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">frobnicate</span><span class="p">()</span> <span class="k">as</span> <span class="n">foo</span><span class="p">:</span> <span class="c1"># type: int</span>
|
||
<span class="c1"># Here foo is an int</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">points</span><span class="p">:</span> <span class="c1"># type: float, float</span>
|
||
<span class="c1"># Here x and y are floats</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In stubs it may be useful to declare the existence of a variable
|
||
without giving it an initial value. This can be done using <a class="pep reference internal" href="../pep-0526/" title="PEP 526 – Syntax for Variable Annotations">PEP 526</a>
|
||
variable annotation syntax:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">IO</span>
|
||
|
||
<span class="n">stream</span><span class="p">:</span> <span class="n">IO</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The above syntax is acceptable in stubs for all versions of Python.
|
||
However, in non-stub code for versions of Python 3.5 and earlier
|
||
there is a special case:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">IO</span>
|
||
|
||
<span class="n">stream</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># type: IO[str]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Type checkers should not complain about this (despite the value
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code> not matching the given type), nor should they change the
|
||
inferred type to <code class="docutils literal notranslate"><span class="pre">Optional[...]</span></code> (despite the rule that does this
|
||
for annotated arguments with a default value of <code class="docutils literal notranslate"><span class="pre">None</span></code>). The
|
||
assumption here is that other code will ensure that the variable is
|
||
given a value of the proper type, and all uses can assume that the
|
||
variable has the given type.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> comment should be put on the line that the
|
||
error refers to:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">http.client</span>
|
||
<span class="n">errors</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s1">'not_found'</span><span class="p">:</span> <span class="n">http</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">NOT_FOUND</span> <span class="c1"># type: ignore</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> comment on a line by itself at the top of a file,
|
||
before any docstrings, imports, or other executable code, silences all
|
||
errors in the file. Blank lines and other comments, such as shebang
|
||
lines and coding cookies, may precede the <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> comment.</p>
|
||
<p>In some cases, linting tools or other comments may be needed on the same
|
||
line as a type comment. In these cases, the type comment should be before
|
||
other comments and linting markers:</p>
|
||
<blockquote>
|
||
<div># type: ignore # <comment or other marker></div></blockquote>
|
||
<p>If type hinting proves useful in general, a syntax for typing variables
|
||
may be provided in a future Python version. (<strong>UPDATE</strong>: This syntax
|
||
was added in Python 3.6 through <a class="pep reference internal" href="../pep-0526/" title="PEP 526 – Syntax for Variable Annotations">PEP 526</a>.)</p>
|
||
</section>
|
||
<section id="casts">
|
||
<h2><a class="toc-backref" href="#casts" role="doc-backlink">Casts</a></h2>
|
||
<p>Occasionally the type checker may need a different kind of hint: the
|
||
programmer may know that an expression is of a more constrained type
|
||
than a type checker may be able to infer. For example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">cast</span>
|
||
|
||
<span class="k">def</span> <span class="nf">find_first_str</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">object</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||
<span class="n">index</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="nb">str</span><span class="p">))</span>
|
||
<span class="c1"># We only get here if there's at least one string in a</span>
|
||
<span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="n">index</span><span class="p">])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Some type checkers may not be able to infer that the type of
|
||
<code class="docutils literal notranslate"><span class="pre">a[index]</span></code> is <code class="docutils literal notranslate"><span class="pre">str</span></code> and only infer <code class="docutils literal notranslate"><span class="pre">object</span></code> or <code class="docutils literal notranslate"><span class="pre">Any</span></code>, but we
|
||
know that (if the code gets to that point) it must be a string. The
|
||
<code class="docutils literal notranslate"><span class="pre">cast(t,</span> <span class="pre">x)</span></code> call tells the type checker that we are confident that
|
||
the type of <code class="docutils literal notranslate"><span class="pre">x</span></code> is <code class="docutils literal notranslate"><span class="pre">t</span></code>. At runtime a cast always returns the
|
||
expression unchanged – it does not check the type, and it does not
|
||
convert or coerce the value.</p>
|
||
<p>Casts differ from type comments (see the previous section). When using
|
||
a type comment, the type checker should still verify that the inferred
|
||
type is consistent with the stated type. When using a cast, the type
|
||
checker should blindly believe the programmer. Also, casts can be used
|
||
in expressions, while type comments only apply to assignments.</p>
|
||
</section>
|
||
<section id="newtype-helper-function">
|
||
<h2><a class="toc-backref" href="#newtype-helper-function" role="doc-backlink">NewType helper function</a></h2>
|
||
<p>There are also situations where a programmer might want to avoid logical
|
||
errors by creating simple classes. For example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">UserId</span><span class="p">(</span><span class="nb">int</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="k">def</span> <span class="nf">get_by_user_id</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="n">UserId</span><span class="p">):</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>However, this approach introduces a runtime overhead. To avoid this,
|
||
<code class="docutils literal notranslate"><span class="pre">typing.py</span></code> provides a helper function <code class="docutils literal notranslate"><span class="pre">NewType</span></code> that creates
|
||
simple unique types with almost zero runtime overhead. For a static type
|
||
checker <code class="docutils literal notranslate"><span class="pre">Derived</span> <span class="pre">=</span> <span class="pre">NewType('Derived',</span> <span class="pre">Base)</span></code> is roughly equivalent
|
||
to a definition:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_x</span><span class="p">:</span> <span class="n">Base</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>While at runtime, <code class="docutils literal notranslate"><span class="pre">NewType('Derived',</span> <span class="pre">Base)</span></code> returns a dummy function
|
||
that simply returns its argument. Type checkers require explicit casts
|
||
from <code class="docutils literal notranslate"><span class="pre">int</span></code> where <code class="docutils literal notranslate"><span class="pre">UserId</span></code> is expected, while implicitly casting
|
||
from <code class="docutils literal notranslate"><span class="pre">UserId</span></code> where <code class="docutils literal notranslate"><span class="pre">int</span></code> is expected. Examples:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">UserId</span> <span class="o">=</span> <span class="n">NewType</span><span class="p">(</span><span class="s1">'UserId'</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">name_by_id</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="n">UserId</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
|
||
<span class="n">UserId</span><span class="p">(</span><span class="s1">'user'</span><span class="p">)</span> <span class="c1"># Fails type check</span>
|
||
|
||
<span class="n">name_by_id</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># Fails type check</span>
|
||
<span class="n">name_by_id</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">num</span> <span class="o">=</span> <span class="n">UserId</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="c1"># type: int</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><code class="docutils literal notranslate"><span class="pre">NewType</span></code> accepts exactly two arguments: a name for the new unique type,
|
||
and a base class. The latter should be a proper class (i.e.,
|
||
not a type construct like <code class="docutils literal notranslate"><span class="pre">Union</span></code>, etc.), or another unique type created
|
||
by calling <code class="docutils literal notranslate"><span class="pre">NewType</span></code>. The function returned by <code class="docutils literal notranslate"><span class="pre">NewType</span></code>
|
||
accepts only one argument; this is equivalent to supporting only one
|
||
constructor accepting an instance of the base class (see above). Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">PacketId</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">major</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">minor</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_major</span> <span class="o">=</span> <span class="n">major</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_minor</span> <span class="o">=</span> <span class="n">minor</span>
|
||
|
||
<span class="n">TcpPacketId</span> <span class="o">=</span> <span class="n">NewType</span><span class="p">(</span><span class="s1">'TcpPacketId'</span><span class="p">,</span> <span class="n">PacketId</span><span class="p">)</span>
|
||
|
||
<span class="n">packet</span> <span class="o">=</span> <span class="n">PacketId</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
|
||
<span class="n">tcp_packet</span> <span class="o">=</span> <span class="n">TcpPacketId</span><span class="p">(</span><span class="n">packet</span><span class="p">)</span> <span class="c1"># OK</span>
|
||
|
||
<span class="n">tcp_packet</span> <span class="o">=</span> <span class="n">TcpPacketId</span><span class="p">(</span><span class="mi">127</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1"># Fails in type checker and at runtime</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Both <code class="docutils literal notranslate"><span class="pre">isinstance</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass</span></code>, as well as subclassing will fail
|
||
for <code class="docutils literal notranslate"><span class="pre">NewType('Derived',</span> <span class="pre">Base)</span></code> since function objects don’t support
|
||
these operations.</p>
|
||
</section>
|
||
<section id="stub-files">
|
||
<h2><a class="toc-backref" href="#stub-files" role="doc-backlink">Stub Files</a></h2>
|
||
<p>Stub files are files containing type hints that are only for use by
|
||
the type checker, not at runtime. There are several use cases for
|
||
stub files:</p>
|
||
<ul class="simple">
|
||
<li>Extension modules</li>
|
||
<li>Third-party modules whose authors have not yet added type hints</li>
|
||
<li>Standard library modules for which type hints have not yet been
|
||
written</li>
|
||
<li>Modules that must be compatible with Python 2 and 3</li>
|
||
<li>Modules that use annotations for other purposes</li>
|
||
</ul>
|
||
<p>Stub files have the same syntax as regular Python modules. There is one
|
||
feature of the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module that is different in stub files:
|
||
the <code class="docutils literal notranslate"><span class="pre">@overload</span></code> decorator described below.</p>
|
||
<p>The type checker should only check function signatures in stub files;
|
||
It is recommended that function bodies in stub files just be a single
|
||
ellipsis (<code class="docutils literal notranslate"><span class="pre">...</span></code>).</p>
|
||
<p>The type checker should have a configurable search path for stub files.
|
||
If a stub file is found the type checker should not read the
|
||
corresponding “real” module.</p>
|
||
<p>While stub files are syntactically valid Python modules, they use the
|
||
<code class="docutils literal notranslate"><span class="pre">.pyi</span></code> extension to make it possible to maintain stub files in the
|
||
same directory as the corresponding real module. This also reinforces
|
||
the notion that no runtime behavior should be expected of stub files.</p>
|
||
<p>Additional notes on stub files:</p>
|
||
<ul>
|
||
<li>Modules and variables imported into the stub are not considered
|
||
exported from the stub unless the import uses the <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">...</span> <span class="pre">as</span>
|
||
<span class="pre">...</span></code> form or the equivalent <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">...</span> <span class="pre">import</span> <span class="pre">...</span> <span class="pre">as</span> <span class="pre">...</span></code> form.
|
||
(<em>UPDATE:</em> To clarify, the intention here is that only names
|
||
imported using the form <code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">as</span> <span class="pre">X</span></code> will be exported, i.e. the name
|
||
before and after <code class="docutils literal notranslate"><span class="pre">as</span></code> must be the same.)</li>
|
||
<li>However, as an exception to the previous bullet, all objects
|
||
imported into a stub using <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">...</span> <span class="pre">import</span> <span class="pre">*</span></code> are considered
|
||
exported. (This makes it easier to re-export all objects from a
|
||
given module that may vary by Python version.)</li>
|
||
<li>Just like in <a class="reference external" href="https://docs.python.org/3/reference/import.html#submodules">normal Python files</a>, submodules
|
||
automatically become exported attributes of their parent module
|
||
when imported. For example, if the <code class="docutils literal notranslate"><span class="pre">spam</span></code> package has the
|
||
following directory structure:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">spam</span><span class="o">/</span>
|
||
<span class="fm">__init__</span><span class="o">.</span><span class="n">pyi</span>
|
||
<span class="n">ham</span><span class="o">.</span><span class="n">pyi</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>where <code class="docutils literal notranslate"><span class="pre">__init__.pyi</span></code> contains a line such as <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">.</span> <span class="pre">import</span> <span class="pre">ham</span></code>
|
||
or <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">.ham</span> <span class="pre">import</span> <span class="pre">Ham</span></code>, then <code class="docutils literal notranslate"><span class="pre">ham</span></code> is an exported attribute
|
||
of <code class="docutils literal notranslate"><span class="pre">spam</span></code>.</p>
|
||
</li>
|
||
<li>Stub files may be incomplete. To make type checkers aware of this, the file
|
||
can contain the following code:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__getattr__</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="o">-></span> <span class="n">Any</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Any identifier not defined in the stub is therefore assumed to be of type
|
||
<code class="docutils literal notranslate"><span class="pre">Any</span></code>.</p>
|
||
</li>
|
||
</ul>
|
||
<section id="function-method-overloading">
|
||
<h3><a class="toc-backref" href="#function-method-overloading" role="doc-backlink">Function/method overloading</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">@overload</span></code> decorator allows describing functions and methods
|
||
that support multiple different combinations of argument types. This
|
||
pattern is used frequently in builtin modules and types. For example,
|
||
the <code class="docutils literal notranslate"><span class="pre">__getitem__()</span></code> method of the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> type can be described as
|
||
follows:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">overload</span>
|
||
|
||
<span class="k">class</span> <span class="nc">bytes</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">i</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span> <span class="o">...</span>
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">:</span> <span class="nb">slice</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bytes</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This description is more precise than would be possible using unions
|
||
(which cannot express the relationship between the argument and return
|
||
types):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Union</span>
|
||
|
||
<span class="k">class</span> <span class="nc">bytes</span><span class="p">:</span>
|
||
<span class="o">...</span>
|
||
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">slice</span><span class="p">])</span> <span class="o">-></span> <span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">]:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Another example where <code class="docutils literal notranslate"><span class="pre">@overload</span></code> comes in handy is the type of the
|
||
builtin <code class="docutils literal notranslate"><span class="pre">map()</span></code> function, which takes a different number of
|
||
arguments depending on the type of the callable:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">Iterator</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">,</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">overload</span>
|
||
|
||
<span class="n">T1</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T1'</span><span class="p">)</span>
|
||
<span class="n">T2</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T2'</span><span class="p">)</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="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">map</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="n">T1</span><span class="p">],</span> <span class="n">S</span><span class="p">],</span> <span class="n">iter1</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T1</span><span class="p">])</span> <span class="o">-></span> <span class="n">Iterator</span><span class="p">[</span><span class="n">S</span><span class="p">]:</span> <span class="o">...</span>
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">map</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="n">T1</span><span class="p">,</span> <span class="n">T2</span><span class="p">],</span> <span class="n">S</span><span class="p">],</span>
|
||
<span class="n">iter1</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T1</span><span class="p">],</span> <span class="n">iter2</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T2</span><span class="p">])</span> <span class="o">-></span> <span class="n">Iterator</span><span class="p">[</span><span class="n">S</span><span class="p">]:</span> <span class="o">...</span>
|
||
<span class="c1"># ... and we could add more items to support more than two iterables</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that we could also easily add items to support <code class="docutils literal notranslate"><span class="pre">map(None,</span> <span class="pre">...)</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">map</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="n">iter1</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T1</span><span class="p">])</span> <span class="o">-></span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T1</span><span class="p">]:</span> <span class="o">...</span>
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">map</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||
<span class="n">iter1</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T1</span><span class="p">],</span>
|
||
<span class="n">iter2</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">T2</span><span class="p">])</span> <span class="o">-></span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">T1</span><span class="p">,</span> <span class="n">T2</span><span class="p">]]:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Uses of the <code class="docutils literal notranslate"><span class="pre">@overload</span></code> decorator as shown above are suitable for
|
||
stub files. In regular modules, a series of <code class="docutils literal notranslate"><span class="pre">@overload</span></code>-decorated
|
||
definitions must be followed by exactly one
|
||
non-<code class="docutils literal notranslate"><span class="pre">@overload</span></code>-decorated definition (for the same function/method).
|
||
The <code class="docutils literal notranslate"><span class="pre">@overload</span></code>-decorated definitions are for the benefit of the
|
||
type checker only, since they will be overwritten by the
|
||
non-<code class="docutils literal notranslate"><span class="pre">@overload</span></code>-decorated definition, while the latter is used at
|
||
runtime but should be ignored by a type checker. At runtime, calling
|
||
a <code class="docutils literal notranslate"><span class="pre">@overload</span></code>-decorated function directly will raise
|
||
<code class="docutils literal notranslate"><span class="pre">NotImplementedError</span></code>. Here’s an example of a non-stub overload
|
||
that can’t easily be expressed using a union or a type variable:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">utf8</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="kc">None</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="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">utf8</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bytes</span><span class="p">:</span>
|
||
<span class="k">pass</span>
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">utf8</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">unicode</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bytes</span><span class="p">:</span>
|
||
<span class="k">pass</span>
|
||
<span class="k">def</span> <span class="nf">utf8</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
|
||
<span class="o"><</span><span class="n">actual</span> <span class="n">implementation</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>NOTE: While it would be possible to provide a multiple dispatch
|
||
implementation using this syntax, its implementation would require
|
||
using <code class="docutils literal notranslate"><span class="pre">sys._getframe()</span></code>, which is frowned upon. Also, designing and
|
||
implementing an efficient multiple dispatch mechanism is hard, which
|
||
is why previous attempts were abandoned in favor of
|
||
<code class="docutils literal notranslate"><span class="pre">functools.singledispatch()</span></code>. (See <a class="pep reference internal" href="../pep-0443/" title="PEP 443 – Single-dispatch generic functions">PEP 443</a>, especially its section
|
||
“Alternative approaches”.) In the future we may come up with a
|
||
satisfactory multiple dispatch design, but we don’t want such a design
|
||
to be constrained by the overloading syntax defined for type hints in
|
||
stub files. It is also possible that both features will develop
|
||
independent from each other (since overloading in the type checker
|
||
has different use cases and requirements than multiple dispatch
|
||
at runtime – e.g. the latter is unlikely to support generic types).</p>
|
||
<p>A constrained <code class="docutils literal notranslate"><span class="pre">TypeVar</span></code> type can often be used instead of using the
|
||
<code class="docutils literal notranslate"><span class="pre">@overload</span></code> decorator. For example, the definitions of <code class="docutils literal notranslate"><span class="pre">concat1</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">concat2</span></code> in this stub file are equivalent:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span><span class="p">,</span> <span class="n">Text</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="n">Text</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">concat1</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">AnyStr</span><span class="p">,</span> <span class="n">y</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="o">...</span>
|
||
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">concat2</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span> <span class="o">...</span>
|
||
<span class="nd">@overload</span>
|
||
<span class="k">def</span> <span class="nf">concat2</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bytes</span><span class="p">:</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Some functions, such as <code class="docutils literal notranslate"><span class="pre">map</span></code> or <code class="docutils literal notranslate"><span class="pre">bytes.__getitem__</span></code> above, can’t
|
||
be represented precisely using type variables. However, unlike
|
||
<code class="docutils literal notranslate"><span class="pre">@overload</span></code>, type variables can also be used outside stub files. We
|
||
recommend that <code class="docutils literal notranslate"><span class="pre">@overload</span></code> is only used in cases where a type
|
||
variable is not sufficient, due to its special stub-only status.</p>
|
||
<p>Another important difference between type variables such as <code class="docutils literal notranslate"><span class="pre">AnyStr</span></code>
|
||
and using <code class="docutils literal notranslate"><span class="pre">@overload</span></code> is that the prior can also be used to define
|
||
constraints for generic class type parameters. For example, the type
|
||
parameter of the generic class <code class="docutils literal notranslate"><span class="pre">typing.IO</span></code> is constrained (only
|
||
<code class="docutils literal notranslate"><span class="pre">IO[str]</span></code>, <code class="docutils literal notranslate"><span class="pre">IO[bytes]</span></code> and <code class="docutils literal notranslate"><span class="pre">IO[Any]</span></code> are valid):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">IO</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">AnyStr</span><span class="p">]):</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="storing-and-distributing-stub-files">
|
||
<h3><a class="toc-backref" href="#storing-and-distributing-stub-files" role="doc-backlink">Storing and distributing stub files</a></h3>
|
||
<p>The easiest form of stub file storage and distribution is to put them
|
||
alongside Python modules in the same directory. This makes them easy to
|
||
find by both programmers and the tools. However, since package
|
||
maintainers are free not to add type hinting to their packages,
|
||
third-party stubs installable by <code class="docutils literal notranslate"><span class="pre">pip</span></code> from PyPI are also supported.
|
||
In this case we have to consider three issues: naming, versioning,
|
||
installation path.</p>
|
||
<p>This PEP does not provide a recommendation on a naming scheme that
|
||
should be used for third-party stub file packages. Discoverability will
|
||
hopefully be based on package popularity, like with Django packages for
|
||
example.</p>
|
||
<p>Third-party stubs have to be versioned using the lowest version of the
|
||
source package that is compatible. Example: FooPackage has versions
|
||
1.0, 1.1, 1.2, 1.3, 2.0, 2.1, 2.2. There are API changes in versions
|
||
1.1, 2.0 and 2.2. The stub file package maintainer is free to release
|
||
stubs for all versions but at least 1.0, 1.1, 2.0 and 2.2 are needed
|
||
to enable the end user type check all versions. This is because the
|
||
user knows that the closest <em>lower or equal</em> version of stubs is
|
||
compatible. In the provided example, for FooPackage 1.3 the user would
|
||
choose stubs version 1.1.</p>
|
||
<p>Note that if the user decides to use the “latest” available source
|
||
package, using the “latest” stub files should generally also work if
|
||
they’re updated often.</p>
|
||
<p>Third-party stub packages can use any location for stub storage. Type
|
||
checkers should search for them using PYTHONPATH. A default fallback
|
||
directory that is always checked is <code class="docutils literal notranslate"><span class="pre">shared/typehints/pythonX.Y/</span></code> (for
|
||
some PythonX.Y as determined by the type checker, not just the installed
|
||
version). Since there can only be one package installed for a given Python
|
||
version per environment, no additional versioning is performed under that
|
||
directory (just like bare directory installs by <code class="docutils literal notranslate"><span class="pre">pip</span></code> in site-packages).
|
||
Stub file package authors might use the following snippet in <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">...</span>
|
||
<span class="n">data_files</span><span class="o">=</span><span class="p">[</span>
|
||
<span class="p">(</span>
|
||
<span class="s1">'shared/typehints/python</span><span class="si">{}</span><span class="s1">.</span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">*</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[:</span><span class="mi">2</span><span class="p">]),</span>
|
||
<span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">SRC_PATH</span><span class="p">)</span><span class="o">.</span><span class="n">glob</span><span class="p">(</span><span class="s1">'**/*.pyi'</span><span class="p">),</span>
|
||
<span class="p">),</span>
|
||
<span class="p">],</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>(<em>UPDATE:</em> As of June 2018 the recommended way to distribute type
|
||
hints for third-party packages has changed – in addition to typeshed
|
||
(see the next section) there is now a standard for distributing type
|
||
hints, <a class="pep reference internal" href="../pep-0561/" title="PEP 561 – Distributing and Packaging Type Information">PEP 561</a>. It supports separately installable packages containing
|
||
stubs, stub files included in the same distribution as the executable
|
||
code of a package, and inline type hints, the latter two options
|
||
enabled by including a file named <code class="docutils literal notranslate"><span class="pre">py.typed</span></code> in the package.)</p>
|
||
</section>
|
||
<section id="the-typeshed-repo">
|
||
<h3><a class="toc-backref" href="#the-typeshed-repo" role="doc-backlink">The Typeshed Repo</a></h3>
|
||
<p>There is a <a class="reference external" href="https://github.com/python/typeshed">shared repository</a> where useful stubs are being
|
||
collected. Policies regarding the stubs collected here will be
|
||
decided separately and reported in the repo’s documentation.
|
||
Note that stubs for a given package will not be included here
|
||
if the package owners have specifically requested that they be omitted.</p>
|
||
</section>
|
||
</section>
|
||
<section id="exceptions">
|
||
<h2><a class="toc-backref" href="#exceptions" role="doc-backlink">Exceptions</a></h2>
|
||
<p>No syntax for listing explicitly raised exceptions is proposed.
|
||
Currently the only known use case for this feature is documentational,
|
||
in which case the recommendation is to put this information in a
|
||
docstring.</p>
|
||
</section>
|
||
<section id="the-typing-module">
|
||
<h2><a class="toc-backref" href="#the-typing-module" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">typing</span></code> Module</a></h2>
|
||
<p>To open the usage of static type checking to Python 3.5 as well as older
|
||
versions, a uniform namespace is required. For this purpose, a new
|
||
module in the standard library is introduced called <code class="docutils literal notranslate"><span class="pre">typing</span></code>.</p>
|
||
<p>It defines the fundamental building blocks for constructing types
|
||
(e.g. <code class="docutils literal notranslate"><span class="pre">Any</span></code>), types representing generic variants of builtin
|
||
collections (e.g. <code class="docutils literal notranslate"><span class="pre">List</span></code>), types representing generic
|
||
collection ABCs (e.g. <code class="docutils literal notranslate"><span class="pre">Sequence</span></code>), and a small collection of
|
||
convenience definitions.</p>
|
||
<p>Note that special type constructs, such as <code class="docutils literal notranslate"><span class="pre">Any</span></code>, <code class="docutils literal notranslate"><span class="pre">Union</span></code>,
|
||
and type variables defined using <code class="docutils literal notranslate"><span class="pre">TypeVar</span></code> are only supported
|
||
in the type annotation context, and <code class="docutils literal notranslate"><span class="pre">Generic</span></code> may only be used
|
||
as a base class. All of these (except for unparameterized generics)
|
||
will raise <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> if 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>.</p>
|
||
<p>Fundamental building blocks:</p>
|
||
<ul class="simple">
|
||
<li>Any, used as <code class="docutils literal notranslate"><span class="pre">def</span> <span class="pre">get(key:</span> <span class="pre">str)</span> <span class="pre">-></span> <span class="pre">Any:</span> <span class="pre">...</span></code></li>
|
||
<li>Union, used as <code class="docutils literal notranslate"><span class="pre">Union[Type1,</span> <span class="pre">Type2,</span> <span class="pre">Type3]</span></code></li>
|
||
<li>Callable, used as <code class="docutils literal notranslate"><span class="pre">Callable[[Arg1Type,</span> <span class="pre">Arg2Type],</span> <span class="pre">ReturnType]</span></code></li>
|
||
<li>Tuple, used by listing the element types, for example
|
||
<code class="docutils literal notranslate"><span class="pre">Tuple[int,</span> <span class="pre">int,</span> <span class="pre">str]</span></code>.
|
||
The empty tuple can be typed as <code class="docutils literal notranslate"><span class="pre">Tuple[()]</span></code>.
|
||
Arbitrary-length homogeneous tuples can be expressed
|
||
using one type and ellipsis, for example <code class="docutils literal notranslate"><span class="pre">Tuple[int,</span> <span class="pre">...]</span></code>.
|
||
(The <code class="docutils literal notranslate"><span class="pre">...</span></code> here are part of the syntax, a literal ellipsis.)</li>
|
||
<li>TypeVar, used as <code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">=</span> <span class="pre">TypeVar('X',</span> <span class="pre">Type1,</span> <span class="pre">Type2,</span> <span class="pre">Type3)</span></code> or simply
|
||
<code class="docutils literal notranslate"><span class="pre">Y</span> <span class="pre">=</span> <span class="pre">TypeVar('Y')</span></code> (see above for more details)</li>
|
||
<li>Generic, used to create user-defined generic classes</li>
|
||
<li>Type, used to annotate class objects</li>
|
||
</ul>
|
||
<p>Generic variants of builtin collections:</p>
|
||
<ul class="simple">
|
||
<li>Dict, used as <code class="docutils literal notranslate"><span class="pre">Dict[key_type,</span> <span class="pre">value_type]</span></code></li>
|
||
<li>DefaultDict, used as <code class="docutils literal notranslate"><span class="pre">DefaultDict[key_type,</span> <span class="pre">value_type]</span></code>,
|
||
a generic variant of <code class="docutils literal notranslate"><span class="pre">collections.defaultdict</span></code></li>
|
||
<li>List, used as <code class="docutils literal notranslate"><span class="pre">List[element_type]</span></code></li>
|
||
<li>Set, used as <code class="docutils literal notranslate"><span class="pre">Set[element_type]</span></code>. See remark for <code class="docutils literal notranslate"><span class="pre">AbstractSet</span></code>
|
||
below.</li>
|
||
<li>FrozenSet, used as <code class="docutils literal notranslate"><span class="pre">FrozenSet[element_type]</span></code></li>
|
||
</ul>
|
||
<p>Note: <code class="docutils literal notranslate"><span class="pre">Dict</span></code>, <code class="docutils literal notranslate"><span class="pre">DefaultDict</span></code>, <code class="docutils literal notranslate"><span class="pre">List</span></code>, <code class="docutils literal notranslate"><span class="pre">Set</span></code> and <code class="docutils literal notranslate"><span class="pre">FrozenSet</span></code>
|
||
are mainly useful for annotating return values.
|
||
For arguments, prefer the abstract collection types defined below,
|
||
e.g. <code class="docutils literal notranslate"><span class="pre">Mapping</span></code>, <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> or <code class="docutils literal notranslate"><span class="pre">AbstractSet</span></code>.</p>
|
||
<p>Generic variants of container ABCs (and a few non-containers):</p>
|
||
<ul class="simple">
|
||
<li>Awaitable</li>
|
||
<li>AsyncIterable</li>
|
||
<li>AsyncIterator</li>
|
||
<li>ByteString</li>
|
||
<li>Callable (see above, listed here for completeness)</li>
|
||
<li>Collection</li>
|
||
<li>Container</li>
|
||
<li>ContextManager</li>
|
||
<li>Coroutine</li>
|
||
<li>Generator, used as <code class="docutils literal notranslate"><span class="pre">Generator[yield_type,</span> <span class="pre">send_type,</span>
|
||
<span class="pre">return_type]</span></code>. This represents the return value of generator
|
||
functions. It is a subtype of <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> and it has additional
|
||
type variables for the type accepted by the <code class="docutils literal notranslate"><span class="pre">send()</span></code> method (it
|
||
is contravariant in this variable – a generator that accepts sending it
|
||
<code class="docutils literal notranslate"><span class="pre">Employee</span></code> instance is valid in a context where a generator is required
|
||
that accepts sending it <code class="docutils literal notranslate"><span class="pre">Manager</span></code> instances) and the return type of the
|
||
generator.</li>
|
||
<li>Hashable (not generic, but present for completeness)</li>
|
||
<li>ItemsView</li>
|
||
<li>Iterable</li>
|
||
<li>Iterator</li>
|
||
<li>KeysView</li>
|
||
<li>Mapping</li>
|
||
<li>MappingView</li>
|
||
<li>MutableMapping</li>
|
||
<li>MutableSequence</li>
|
||
<li>MutableSet</li>
|
||
<li>Sequence</li>
|
||
<li>Set, renamed to <code class="docutils literal notranslate"><span class="pre">AbstractSet</span></code>. This name change was required
|
||
because <code class="docutils literal notranslate"><span class="pre">Set</span></code> in the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module means <code class="docutils literal notranslate"><span class="pre">set()</span></code> with
|
||
generics.</li>
|
||
<li>Sized (not generic, but present for completeness)</li>
|
||
<li>ValuesView</li>
|
||
</ul>
|
||
<p>A few one-off types are defined that test for single special methods
|
||
(similar to <code class="docutils literal notranslate"><span class="pre">Hashable</span></code> or <code class="docutils literal notranslate"><span class="pre">Sized</span></code>):</p>
|
||
<ul class="simple">
|
||
<li>Reversible, to test for <code class="docutils literal notranslate"><span class="pre">__reversed__</span></code></li>
|
||
<li>SupportsAbs, to test for <code class="docutils literal notranslate"><span class="pre">__abs__</span></code></li>
|
||
<li>SupportsComplex, to test for <code class="docutils literal notranslate"><span class="pre">__complex__</span></code></li>
|
||
<li>SupportsFloat, to test for <code class="docutils literal notranslate"><span class="pre">__float__</span></code></li>
|
||
<li>SupportsInt, to test for <code class="docutils literal notranslate"><span class="pre">__int__</span></code></li>
|
||
<li>SupportsRound, to test for <code class="docutils literal notranslate"><span class="pre">__round__</span></code></li>
|
||
<li>SupportsBytes, to test for <code class="docutils literal notranslate"><span class="pre">__bytes__</span></code></li>
|
||
</ul>
|
||
<p>Convenience definitions:</p>
|
||
<ul class="simple">
|
||
<li>Optional, defined by <code class="docutils literal notranslate"><span class="pre">Optional[t]</span> <span class="pre">==</span> <span class="pre">Union[t,</span> <span class="pre">None]</span></code></li>
|
||
<li>Text, a simple alias for <code class="docutils literal notranslate"><span class="pre">str</span></code> in Python 3, for <code class="docutils literal notranslate"><span class="pre">unicode</span></code> in Python 2</li>
|
||
<li>AnyStr, defined as <code class="docutils literal notranslate"><span class="pre">TypeVar('AnyStr',</span> <span class="pre">Text,</span> <span class="pre">bytes)</span></code></li>
|
||
<li>NamedTuple, used as
|
||
<code class="docutils literal notranslate"><span class="pre">NamedTuple(type_name,</span> <span class="pre">[(field_name,</span> <span class="pre">field_type),</span> <span class="pre">...])</span></code>
|
||
and equivalent to
|
||
<code class="docutils literal notranslate"><span class="pre">collections.namedtuple(type_name,</span> <span class="pre">[field_name,</span> <span class="pre">...])</span></code>.
|
||
This is useful to declare the types of the fields of a named tuple
|
||
type.</li>
|
||
<li>NewType, used to create unique types with little runtime overhead
|
||
<code class="docutils literal notranslate"><span class="pre">UserId</span> <span class="pre">=</span> <span class="pre">NewType('UserId',</span> <span class="pre">int)</span></code></li>
|
||
<li>cast(), described earlier</li>
|
||
<li>@no_type_check, a decorator to disable type checking per class or
|
||
function (see below)</li>
|
||
<li>@no_type_check_decorator, a decorator to create your own decorators
|
||
with the same meaning as <code class="docutils literal notranslate"><span class="pre">@no_type_check</span></code> (see below)</li>
|
||
<li>@type_check_only, a decorator only available during type checking
|
||
for use in stub files (see above); marks a class or function as
|
||
unavailable during runtime</li>
|
||
<li>@overload, described earlier</li>
|
||
<li>get_type_hints(), a utility function to retrieve the type hints from a
|
||
function or method. Given a function or method object, it returns
|
||
a dict with the same format as <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>, but evaluating
|
||
forward references (which are given as string literals) as expressions
|
||
in the context of the original function or method definition.</li>
|
||
<li>TYPE_CHECKING, <code class="docutils literal notranslate"><span class="pre">False</span></code> at runtime but <code class="docutils literal notranslate"><span class="pre">True</span></code> to type checkers</li>
|
||
</ul>
|
||
<p>I/O related types:</p>
|
||
<ul class="simple">
|
||
<li>IO (generic over <code class="docutils literal notranslate"><span class="pre">AnyStr</span></code>)</li>
|
||
<li>BinaryIO (a simple subtype of <code class="docutils literal notranslate"><span class="pre">IO[bytes]</span></code>)</li>
|
||
<li>TextIO (a simple subtype of <code class="docutils literal notranslate"><span class="pre">IO[str]</span></code>)</li>
|
||
</ul>
|
||
<p>Types related to regular expressions and the <code class="docutils literal notranslate"><span class="pre">re</span></code> module:</p>
|
||
<ul class="simple">
|
||
<li>Match and Pattern, types of <code class="docutils literal notranslate"><span class="pre">re.match()</span></code> and <code class="docutils literal notranslate"><span class="pre">re.compile()</span></code>
|
||
results (generic over <code class="docutils literal notranslate"><span class="pre">AnyStr</span></code>)</li>
|
||
</ul>
|
||
</section>
|
||
<section id="suggested-syntax-for-python-2-7-and-straddling-code">
|
||
<h2><a class="toc-backref" href="#suggested-syntax-for-python-2-7-and-straddling-code" role="doc-backlink">Suggested syntax for Python 2.7 and straddling code</a></h2>
|
||
<p>Some tools may want to support type annotations in code that must be
|
||
compatible with Python 2.7. For this purpose this PEP has a suggested
|
||
(but not mandatory) extension where function annotations are placed in
|
||
a <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span></code> comment. Such a comment must be placed immediately
|
||
following the function header (before the docstring). An example: the
|
||
following Python 3 code:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">embezzle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">account</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">funds</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1000000</span><span class="p">,</span> <span class="o">*</span><span class="n">fake_receipts</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="sd">"""Embezzle funds from account using fake receipts."""</span>
|
||
<span class="o"><</span><span class="n">code</span> <span class="n">goes</span> <span class="n">here</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>is equivalent to the following:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">embezzle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">account</span><span class="p">,</span> <span class="n">funds</span><span class="o">=</span><span class="mi">1000000</span><span class="p">,</span> <span class="o">*</span><span class="n">fake_receipts</span><span class="p">):</span>
|
||
<span class="c1"># type: (str, int, *str) -> None</span>
|
||
<span class="w"> </span><span class="sd">"""Embezzle funds from account using fake receipts."""</span>
|
||
<span class="o"><</span><span class="n">code</span> <span class="n">goes</span> <span class="n">here</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that for methods, no type is needed for <code class="docutils literal notranslate"><span class="pre">self</span></code>.</p>
|
||
<p>For an argument-less method it would look like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">load_cache</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># type: () -> bool</span>
|
||
<span class="o"><</span><span class="n">code</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Sometimes you want to specify the return type for a function or method
|
||
without (yet) specifying the argument types. To support this
|
||
explicitly, the argument list may be replaced with an ellipsis.
|
||
Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">sender</span><span class="p">,</span> <span class="n">cc</span><span class="p">,</span> <span class="n">bcc</span><span class="p">,</span> <span class="n">subject</span><span class="p">,</span> <span class="n">body</span><span class="p">):</span>
|
||
<span class="c1"># type: (...) -> bool</span>
|
||
<span class="w"> </span><span class="sd">"""Send an email message. Return True if successful."""</span>
|
||
<span class="o"><</span><span class="n">code</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Sometimes you have a long list of parameters and specifying their
|
||
types in a single <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span></code> comment would be awkward. To this end
|
||
you may list the arguments one per line and add a <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span></code> comment
|
||
per line after an argument’s associated comma, if any.
|
||
To specify the return type use the ellipsis syntax. Specifying the return
|
||
type is not mandatory and not every argument needs to be given a type.
|
||
A line with a <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span></code> comment should contain exactly one argument.
|
||
The type comment for the last argument (if any) should precede the close
|
||
parenthesis. Example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="c1"># type: Union[str, List[str]]</span>
|
||
<span class="n">sender</span><span class="p">,</span> <span class="c1"># type: str</span>
|
||
<span class="n">cc</span><span class="p">,</span> <span class="c1"># type: Optional[List[str]]</span>
|
||
<span class="n">bcc</span><span class="p">,</span> <span class="c1"># type: Optional[List[str]]</span>
|
||
<span class="n">subject</span><span class="o">=</span><span class="s1">''</span><span class="p">,</span>
|
||
<span class="n">body</span><span class="o">=</span><span class="kc">None</span> <span class="c1"># type: List[str]</span>
|
||
<span class="p">):</span>
|
||
<span class="c1"># type: (...) -> bool</span>
|
||
<span class="w"> </span><span class="sd">"""Send an email message. Return True if successful."""</span>
|
||
<span class="o"><</span><span class="n">code</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Notes:</p>
|
||
<ul>
|
||
<li>Tools that support this syntax should support it regardless of the
|
||
Python version being checked. This is necessary in order to support
|
||
code that straddles Python 2 and Python 3.</li>
|
||
<li>It is not allowed for an argument or return value to have both
|
||
a type annotation and a type comment.</li>
|
||
<li>When using the short form (e.g. <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">(str,</span> <span class="pre">int)</span> <span class="pre">-></span> <span class="pre">None</span></code>)
|
||
every argument must be accounted for, except the first argument of
|
||
instance and class methods (those are usually omitted, but it’s
|
||
allowed to include them).</li>
|
||
<li>The return type is mandatory for the short form. If in Python 3 you
|
||
would omit some argument or the return type, the Python 2 notation
|
||
should use <code class="docutils literal notranslate"><span class="pre">Any</span></code>.</li>
|
||
<li>When using the short form, for <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwds</span></code>, put 1 or 2
|
||
stars in front of the corresponding type annotation. (As with
|
||
Python 3 annotations, the annotation here denotes the type of the
|
||
individual argument values, not of the tuple/dict that you receive
|
||
as the special argument value <code class="docutils literal notranslate"><span class="pre">args</span></code> or <code class="docutils literal notranslate"><span class="pre">kwds</span></code>.)</li>
|
||
<li>Like other type comments, any names used in the annotations must be
|
||
imported or defined by the module containing the annotation.</li>
|
||
<li>When using the short form, the entire annotation must be one line.</li>
|
||
<li>The short form may also occur on the same line as the close
|
||
parenthesis, e.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span> <span class="c1"># type: (int, int) -> int</span>
|
||
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>Misplaced type comments will be flagged as errors by a type checker.
|
||
If necessary, such comments could be commented twice. For example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
|
||
<span class="w"> </span><span class="sd">'''Docstring'''</span>
|
||
<span class="c1"># type: () -> None # Error!</span>
|
||
|
||
<span class="k">def</span> <span class="nf">g</span><span class="p">():</span>
|
||
<span class="w"> </span><span class="sd">'''Docstring'''</span>
|
||
<span class="c1"># # type: () -> None # This is OK</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<p>When checking Python 2.7 code, type checkers should treat the <code class="docutils literal notranslate"><span class="pre">int</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">long</span></code> types as equivalent. For parameters typed as <code class="docutils literal notranslate"><span class="pre">Text</span></code>, arguments of
|
||
type <code class="docutils literal notranslate"><span class="pre">str</span></code> as well as <code class="docutils literal notranslate"><span class="pre">unicode</span></code> should be acceptable.</p>
|
||
</section>
|
||
<section id="rejected-alternatives">
|
||
<h2><a class="toc-backref" href="#rejected-alternatives" role="doc-backlink">Rejected Alternatives</a></h2>
|
||
<p>During discussion of earlier drafts of this PEP, various objections
|
||
were raised and alternatives were proposed. We discuss some of these
|
||
here and explain why we reject them.</p>
|
||
<p>Several main objections were raised.</p>
|
||
<section id="which-brackets-for-generic-type-parameters">
|
||
<h3><a class="toc-backref" href="#which-brackets-for-generic-type-parameters" role="doc-backlink">Which brackets for generic type parameters?</a></h3>
|
||
<p>Most people are familiar with the use of angular brackets
|
||
(e.g. <code class="docutils literal notranslate"><span class="pre">List<int></span></code>) in languages like C++, Java, C# and Swift to
|
||
express the parameterization of generic types. The problem with these
|
||
is that they are really hard to parse, especially for a simple-minded
|
||
parser like Python. In most languages the ambiguities are usually
|
||
dealt with by only allowing angular brackets in specific syntactic
|
||
positions, where general expressions aren’t allowed. (And also by
|
||
using very powerful parsing techniques that can backtrack over an
|
||
arbitrary section of code.)</p>
|
||
<p>But in Python, we’d like type expressions to be (syntactically) the
|
||
same as other expressions, so that we can use e.g. variable assignment
|
||
to create type aliases. Consider this simple type expression:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">List</span><span class="o"><</span><span class="nb">int</span><span class="o">></span>
|
||
</pre></div>
|
||
</div>
|
||
<p>From the Python parser’s perspective, the expression begins with the
|
||
same four tokens (NAME, LESS, NAME, GREATER) as a chained comparison:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o"><</span> <span class="n">b</span> <span class="o">></span> <span class="n">c</span> <span class="c1"># I.e., (a < b) and (b > c)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We can even make up an example that could be parsed both ways:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o"><</span> <span class="n">b</span> <span class="o">></span> <span class="p">[</span> <span class="n">c</span> <span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Assuming we had angular brackets in the language, this could be
|
||
interpreted as either of the following two:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a</span><span class="o"><</span><span class="n">b</span><span class="o">></span><span class="p">)[</span><span class="n">c</span><span class="p">]</span> <span class="c1"># I.e., (a<b>).__getitem__(c)</span>
|
||
<span class="n">a</span> <span class="o"><</span> <span class="n">b</span> <span class="o">></span> <span class="p">([</span><span class="n">c</span><span class="p">])</span> <span class="c1"># I.e., (a < b) and (b > [c])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>It would surely be possible to come up with a rule to disambiguate
|
||
such cases, but to most users the rules would feel arbitrary and
|
||
complex. It would also require us to dramatically change the CPython
|
||
parser (and every other parser for Python). It should be noted that
|
||
Python’s current parser is intentionally “dumb” – a simple grammar is
|
||
easier for users to reason about.</p>
|
||
<p>For all these reasons, square brackets (e.g. <code class="docutils literal notranslate"><span class="pre">List[int]</span></code>) are (and
|
||
have long been) the preferred syntax for generic type parameters.
|
||
They can be implemented by defining the <code class="docutils literal notranslate"><span class="pre">__getitem__()</span></code> method on
|
||
the metaclass, and no new syntax is required at all. This option
|
||
works in all recent versions of Python (starting with Python 2.2).
|
||
Python is not alone in this syntactic choice – generic classes in
|
||
Scala also use square brackets.</p>
|
||
</section>
|
||
<section id="what-about-existing-uses-of-annotations">
|
||
<h3><a class="toc-backref" href="#what-about-existing-uses-of-annotations" role="doc-backlink">What about existing uses of annotations?</a></h3>
|
||
<p>One line of argument points out that <a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a> explicitly supports
|
||
the use of arbitrary expressions in function annotations. The new
|
||
proposal is then considered incompatible with the specification of PEP
|
||
3107.</p>
|
||
<p>Our response to this is that, first of all, the current proposal does
|
||
not introduce any direct incompatibilities, so programs using
|
||
annotations in Python 3.4 will still work correctly and without
|
||
prejudice in Python 3.5.</p>
|
||
<p>We do hope that type hints will eventually become the sole use for
|
||
annotations, but this will require additional discussion and a
|
||
deprecation period after the initial roll-out of the typing module
|
||
with Python 3.5. The current PEP will have provisional status (see
|
||
<a class="pep reference internal" href="../pep-0411/" title="PEP 411 – Provisional packages in the Python standard library">PEP 411</a>) until Python 3.6 is released. The fastest conceivable scheme
|
||
would introduce silent deprecation of non-type-hint annotations in
|
||
3.6, full deprecation in 3.7, and declare type hints as the only
|
||
allowed use of annotations in Python 3.8. This should give authors of
|
||
packages that use annotations plenty of time to devise another
|
||
approach, even if type hints become an overnight success.</p>
|
||
<p>(<em>UPDATE:</em> As of fall 2017, the timeline for the end of provisional
|
||
status for this PEP and for the <code class="docutils literal notranslate"><span class="pre">typing.py</span></code> module has changed, and
|
||
so has the deprecation schedule for other uses of annotations. For
|
||
the updated schedule see <a class="pep reference internal" href="../pep-0563/" title="PEP 563 – Postponed Evaluation of Annotations">PEP 563</a>.)</p>
|
||
<p>Another possible outcome would be that type hints will eventually
|
||
become the default meaning for annotations, but that there will always
|
||
remain an option to disable them. For this purpose the current
|
||
proposal defines a decorator <code class="docutils literal notranslate"><span class="pre">@no_type_check</span></code> which disables the
|
||
default interpretation of annotations as type hints in a given class
|
||
or function. It also defines a meta-decorator
|
||
<code class="docutils literal notranslate"><span class="pre">@no_type_check_decorator</span></code> which can be used to decorate a decorator
|
||
(!), causing annotations in any function or class decorated with the
|
||
latter to be ignored by the type checker.</p>
|
||
<p>There are also <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> comments, and static checkers should
|
||
support configuration options to disable type checking in selected
|
||
packages.</p>
|
||
<p>Despite all these options, proposals have been circulated to allow
|
||
type hints and other forms of annotations to coexist for individual
|
||
arguments. One proposal suggests that if an annotation for a given
|
||
argument is a dictionary literal, each key represents a different form
|
||
of annotation, and the key <code class="docutils literal notranslate"><span class="pre">'type'</span></code> would be use for type hints.
|
||
The problem with this idea and its variants is that the notation
|
||
becomes very “noisy” and hard to read. Also, in most cases where
|
||
existing libraries use annotations, there would be little need to
|
||
combine them with type hints. So the simpler approach of selectively
|
||
disabling type hints appears sufficient.</p>
|
||
</section>
|
||
<section id="the-problem-of-forward-declarations">
|
||
<h3><a class="toc-backref" href="#the-problem-of-forward-declarations" role="doc-backlink">The problem of forward declarations</a></h3>
|
||
<p>The current proposal is admittedly sub-optimal when type hints must
|
||
contain forward references. Python requires all names to be defined
|
||
by the time they are used. Apart from circular imports this is rarely
|
||
a problem: “use” here means “look up at runtime”, and with most
|
||
“forward” references there is no problem in ensuring that a name is
|
||
defined before the function using it is called.</p>
|
||
<p>The problem with type hints is that annotations (per <a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a>, and
|
||
similar to default values) are evaluated at the time a function is
|
||
defined, and thus any names used in an annotation must be already
|
||
defined when the function is being defined. A common scenario is a
|
||
class definition whose methods need to reference the class itself in
|
||
their annotations. (More general, it can also occur with mutually
|
||
recursive classes.) This is natural for container types, for
|
||
example:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Node</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="sd">"""Binary tree node."""</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">left</span><span class="p">:</span> <span class="n">Node</span><span class="p">,</span> <span class="n">right</span><span class="p">:</span> <span class="n">Node</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">left</span> <span class="o">=</span> <span class="n">left</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">right</span> <span class="o">=</span> <span class="n">right</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>As written this will not work, because of the peculiarity in Python
|
||
that class names become defined once the entire body of the class has
|
||
been executed. Our solution, which isn’t particularly elegant, but
|
||
gets the job done, is to allow using string literals in annotations.
|
||
Most of the time you won’t have to use this though – most <em>uses</em> of
|
||
type hints are expected to reference builtin types or types defined in
|
||
other modules.</p>
|
||
<p>A counterproposal would change the semantics of type hints so they
|
||
aren’t evaluated at runtime at all (after all, type checking happens
|
||
off-line, so why would type hints need to be evaluated at runtime at
|
||
all). This of course would run afoul of backwards compatibility,
|
||
since the Python interpreter doesn’t actually know whether a
|
||
particular annotation is meant to be a type hint or something else.</p>
|
||
<p>A compromise is possible where a <code class="docutils literal notranslate"><span class="pre">__future__</span></code> import could enable
|
||
turning <em>all</em> annotations in a given module into string literals, as
|
||
follows:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||
|
||
<span class="k">class</span> <span class="nc">ImSet</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="n">ImSet</span><span class="p">)</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="n">ImSet</span><span class="p">]:</span> <span class="o">...</span>
|
||
|
||
<span class="k">assert</span> <span class="n">ImSet</span><span class="o">.</span><span class="n">add</span><span class="o">.</span><span class="vm">__annotations__</span> <span class="o">==</span> <span class="p">{</span><span class="s1">'a'</span><span class="p">:</span> <span class="s1">'ImSet'</span><span class="p">,</span> <span class="s1">'return'</span><span class="p">:</span> <span class="s1">'List[ImSet]'</span><span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Such a <code class="docutils literal notranslate"><span class="pre">__future__</span></code> import statement may be proposed in a separate
|
||
PEP.</p>
|
||
<p>(<em>UPDATE:</em> That <code class="docutils literal notranslate"><span class="pre">__future__</span></code> import statement and its consequences
|
||
are discussed in <a class="pep reference internal" href="../pep-0563/" title="PEP 563 – Postponed Evaluation of Annotations">PEP 563</a>.)</p>
|
||
</section>
|
||
<section id="the-double-colon">
|
||
<h3><a class="toc-backref" href="#the-double-colon" role="doc-backlink">The double colon</a></h3>
|
||
<p>A few creative souls have tried to invent solutions for this problem.
|
||
For example, it was proposed to use a double colon (<code class="docutils literal notranslate"><span class="pre">::</span></code>) for type
|
||
hints, solving two problems at once: disambiguating between type hints
|
||
and other annotations, and changing the semantics to preclude runtime
|
||
evaluation. There are several things wrong with this idea, however.</p>
|
||
<ul class="simple">
|
||
<li>It’s ugly. The single colon in Python has many uses, and all of
|
||
them look familiar because they resemble the use of the colon in
|
||
English text. This is a general rule of thumb by which Python
|
||
abides for most forms of punctuation; the exceptions are typically
|
||
well known from other programming languages. But this use of <code class="docutils literal notranslate"><span class="pre">::</span></code>
|
||
is unheard of in English, and in other languages (e.g. C++) it is
|
||
used as a scoping operator, which is a very different beast. In
|
||
contrast, the single colon for type hints reads naturally – and no
|
||
wonder, since it was carefully designed for this purpose
|
||
(<a class="reference external" href="https://www.artima.com/weblogs/viewpost.jsp?thread=85551">the idea</a>
|
||
long predates <a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a>). It is also used in the same
|
||
fashion in other languages from Pascal to Swift.</li>
|
||
<li>What would you do for return type annotations?</li>
|
||
<li>It’s actually a feature that type hints are evaluated at runtime.<ul>
|
||
<li>Making type hints available at runtime allows runtime type
|
||
checkers to be built on top of type hints.</li>
|
||
<li>It catches mistakes even when the type checker is not run. Since
|
||
it is a separate program, users may choose not to run it (or even
|
||
install it), but might still want to use type hints as a concise
|
||
form of documentation. Broken type hints are no use even for
|
||
documentation.</li>
|
||
</ul>
|
||
</li>
|
||
<li>Because it’s new syntax, using the double colon for type hints would
|
||
limit them to code that works with Python 3.5 only. By using
|
||
existing syntax, the current proposal can easily work for older
|
||
versions of Python 3. (And in fact mypy supports Python 3.2 and
|
||
newer.)</li>
|
||
<li>If type hints become successful we may well decide to add new syntax
|
||
in the future to declare the type for variables, for example
|
||
<code class="docutils literal notranslate"><span class="pre">var</span> <span class="pre">age:</span> <span class="pre">int</span> <span class="pre">=</span> <span class="pre">42</span></code>. If we were to use a double colon for
|
||
argument type hints, for consistency we’d have to use the same
|
||
convention for future syntax, perpetuating the ugliness.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="other-forms-of-new-syntax">
|
||
<h3><a class="toc-backref" href="#other-forms-of-new-syntax" role="doc-backlink">Other forms of new syntax</a></h3>
|
||
<p>A few other forms of alternative syntax have been proposed, e.g. <a class="reference external" href="https://aroberge.blogspot.com/2015/01/type-hinting-in-python-focus-on.html">the
|
||
introduction</a> of a <code class="docutils literal notranslate"><span class="pre">where</span></code> keyword, and Cobra-inspired
|
||
<code class="docutils literal notranslate"><span class="pre">requires</span></code> clauses. But these all share a problem with the double
|
||
colon: they won’t work for earlier versions of Python 3. The same
|
||
would apply to a new <code class="docutils literal notranslate"><span class="pre">__future__</span></code> import.</p>
|
||
</section>
|
||
<section id="other-backwards-compatible-conventions">
|
||
<h3><a class="toc-backref" href="#other-backwards-compatible-conventions" role="doc-backlink">Other backwards compatible conventions</a></h3>
|
||
<p>The ideas put forward include:</p>
|
||
<ul class="simple">
|
||
<li>A decorator, e.g. <code class="docutils literal notranslate"><span class="pre">@typehints(name=str,</span> <span class="pre">returns=str)</span></code>. This could
|
||
work, but it’s pretty verbose (an extra line, and the argument names
|
||
must be repeated), and a far cry in elegance from the <a class="pep reference internal" href="../pep-3107/" title="PEP 3107 – Function Annotations">PEP 3107</a>
|
||
notation.</li>
|
||
<li>Stub files. We do want stub files, but they are primarily useful
|
||
for adding type hints to existing code that doesn’t lend itself to
|
||
adding type hints, e.g. 3rd party packages, code that needs to
|
||
support both Python 2 and Python 3, and especially extension
|
||
modules. For most situations, having the annotations in line with
|
||
the function definitions makes them much more useful.</li>
|
||
<li>Docstrings. There is an existing convention for docstrings, based
|
||
on the Sphinx notation (<code class="docutils literal notranslate"><span class="pre">:type</span> <span class="pre">arg1:</span> <span class="pre">description</span></code>). This is
|
||
pretty verbose (an extra line per parameter), and not very elegant.
|
||
We could also make up something new, but the annotation syntax is
|
||
hard to beat (because it was designed for this very purpose).</li>
|
||
</ul>
|
||
<p>It’s also been proposed to simply wait another release. But what
|
||
problem would that solve? It would just be procrastination.</p>
|
||
</section>
|
||
</section>
|
||
<section id="pep-development-process">
|
||
<h2><a class="toc-backref" href="#pep-development-process" role="doc-backlink">PEP Development Process</a></h2>
|
||
<p>A live draft for this PEP lives on <a class="reference external" href="https://github.com/python/typing">GitHub</a>. There is also an
|
||
<a class="reference external" href="https://github.com/python/typing/issues">issue tracker</a>, where much of the technical discussion takes
|
||
place.</p>
|
||
<p>The draft on GitHub is updated regularly in small increments. The
|
||
<a class="reference external" href="https://hg.python.org/peps/file/tip/pep-0484.txt">official PEPS repo</a> is (usually) only updated when a new draft
|
||
is posted to python-dev.</p>
|
||
</section>
|
||
<section id="acknowledgements">
|
||
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
||
<p>This document could not be completed without valuable input,
|
||
encouragement and advice from Jim Baker, Jeremy Siek, Michael Matson
|
||
Vitousek, Andrey Vlasovskikh, Radomir Dopieralski, Peter Ludemann,
|
||
and the BDFL-Delegate, Mark Shannon.</p>
|
||
<p>Influences include existing languages, libraries and frameworks
|
||
mentioned in <a class="pep reference internal" href="../pep-0482/" title="PEP 482 – Literature Overview for Type Hints">PEP 482</a>. Many thanks to their creators, in alphabetical
|
||
order: Stefan Behnel, William Edwards, Greg Ewing, Larry Hastings,
|
||
Anders Hejlsberg, Alok Menghrajani, Travis E. Oliphant, Joe Pamer,
|
||
Raoul-Gabriel Urma, and Julien Verlaguet.</p>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document has been placed in the public domain.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0484.rst">https://github.com/python/peps/blob/main/peps/pep-0484.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0484.rst">2023-09-09 17:39:29 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a><ul>
|
||
<li><a class="reference internal" href="#non-goals">Non-goals</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-meaning-of-annotations">The meaning of annotations</a></li>
|
||
<li><a class="reference internal" href="#type-definition-syntax">Type Definition Syntax</a><ul>
|
||
<li><a class="reference internal" href="#acceptable-type-hints">Acceptable type hints</a></li>
|
||
<li><a class="reference internal" href="#using-none">Using None</a></li>
|
||
<li><a class="reference internal" href="#type-aliases">Type aliases</a></li>
|
||
<li><a class="reference internal" href="#callable">Callable</a></li>
|
||
<li><a class="reference internal" href="#generics">Generics</a></li>
|
||
<li><a class="reference internal" href="#user-defined-generic-types">User-defined generic types</a></li>
|
||
<li><a class="reference internal" href="#scoping-rules-for-type-variables">Scoping rules for type variables</a></li>
|
||
<li><a class="reference internal" href="#instantiating-generic-classes-and-type-erasure">Instantiating generic classes and type erasure</a></li>
|
||
<li><a class="reference internal" href="#arbitrary-generic-types-as-base-classes">Arbitrary generic types as base classes</a></li>
|
||
<li><a class="reference internal" href="#abstract-generic-types">Abstract generic types</a></li>
|
||
<li><a class="reference internal" href="#type-variables-with-an-upper-bound">Type variables with an upper bound</a></li>
|
||
<li><a class="reference internal" href="#covariance-and-contravariance">Covariance and contravariance</a></li>
|
||
<li><a class="reference internal" href="#the-numeric-tower">The numeric tower</a></li>
|
||
<li><a class="reference internal" href="#forward-references">Forward references</a></li>
|
||
<li><a class="reference internal" href="#union-types">Union types</a></li>
|
||
<li><a class="reference internal" href="#support-for-singleton-types-in-unions">Support for singleton types in unions</a></li>
|
||
<li><a class="reference internal" href="#the-any-type">The <code class="docutils literal notranslate"><span class="pre">Any</span></code> type</a></li>
|
||
<li><a class="reference internal" href="#the-noreturn-type">The <code class="docutils literal notranslate"><span class="pre">NoReturn</span></code> type</a></li>
|
||
<li><a class="reference internal" href="#the-type-of-class-objects">The type of class objects</a></li>
|
||
<li><a class="reference internal" href="#annotating-instance-and-class-methods">Annotating instance and class methods</a></li>
|
||
<li><a class="reference internal" href="#version-and-platform-checking">Version and platform checking</a></li>
|
||
<li><a class="reference internal" href="#runtime-or-type-checking">Runtime or type checking?</a></li>
|
||
<li><a class="reference internal" href="#arbitrary-argument-lists-and-default-argument-values">Arbitrary argument lists and default argument values</a></li>
|
||
<li><a class="reference internal" href="#positional-only-arguments">Positional-only arguments</a></li>
|
||
<li><a class="reference internal" href="#annotating-generator-functions-and-coroutines">Annotating generator functions and coroutines</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#compatibility-with-other-uses-of-function-annotations">Compatibility with other uses of function annotations</a></li>
|
||
<li><a class="reference internal" href="#type-comments">Type comments</a></li>
|
||
<li><a class="reference internal" href="#casts">Casts</a></li>
|
||
<li><a class="reference internal" href="#newtype-helper-function">NewType helper function</a></li>
|
||
<li><a class="reference internal" href="#stub-files">Stub Files</a><ul>
|
||
<li><a class="reference internal" href="#function-method-overloading">Function/method overloading</a></li>
|
||
<li><a class="reference internal" href="#storing-and-distributing-stub-files">Storing and distributing stub files</a></li>
|
||
<li><a class="reference internal" href="#the-typeshed-repo">The Typeshed Repo</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#exceptions">Exceptions</a></li>
|
||
<li><a class="reference internal" href="#the-typing-module">The <code class="docutils literal notranslate"><span class="pre">typing</span></code> Module</a></li>
|
||
<li><a class="reference internal" href="#suggested-syntax-for-python-2-7-and-straddling-code">Suggested syntax for Python 2.7 and straddling code</a></li>
|
||
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a><ul>
|
||
<li><a class="reference internal" href="#which-brackets-for-generic-type-parameters">Which brackets for generic type parameters?</a></li>
|
||
<li><a class="reference internal" href="#what-about-existing-uses-of-annotations">What about existing uses of annotations?</a></li>
|
||
<li><a class="reference internal" href="#the-problem-of-forward-declarations">The problem of forward declarations</a></li>
|
||
<li><a class="reference internal" href="#the-double-colon">The double colon</a></li>
|
||
<li><a class="reference internal" href="#other-forms-of-new-syntax">Other forms of new syntax</a></li>
|
||
<li><a class="reference internal" href="#other-backwards-compatible-conventions">Other backwards compatible conventions</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#pep-development-process">PEP Development Process</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0484.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> |