698 lines
70 KiB
HTML
698 lines
70 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 692 – Using TypedDict for more precise **kwargs typing | peps.python.org</title>
|
|||
|
<link rel="shortcut icon" href="../_static/py.png">
|
|||
|
<link rel="canonical" href="https://peps.python.org/pep-0692/">
|
|||
|
<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 692 – Using TypedDict for more precise **kwargs typing | peps.python.org'>
|
|||
|
<meta property="og:description" content="Currently **kwargs can be type hinted as long as all of the keyword arguments specified by them are of the same type. However, that behaviour can be very limiting. Therefore, in this PEP we propose a new way to enable more precise **kwargs typing. The n...">
|
|||
|
<meta property="og:type" content="website">
|
|||
|
<meta property="og:url" content="https://peps.python.org/pep-0692/">
|
|||
|
<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="Currently **kwargs can be type hinted as long as all of the keyword arguments specified by them are of the same type. However, that behaviour can be very limiting. Therefore, in this PEP we propose a new way to enable more precise **kwargs typing. The n...">
|
|||
|
<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 692</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 692 – Using TypedDict for more precise **kwargs typing</h1>
|
|||
|
<dl class="rfc2822 field-list simple">
|
|||
|
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">Franek Magiera <framagie at gmail.com></dd>
|
|||
|
<dt class="field-even">Sponsor<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even">Jelle Zijlstra <jelle.zijlstra at gmail.com></dd>
|
|||
|
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/pep-692-using-typeddict-for-more-precise-kwargs-typing/17314">Discourse thread</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-May-2022</dd>
|
|||
|
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even">3.12</dd>
|
|||
|
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/thread/U42MJE6QZYWPVIFHJIGIT7OE52ZGIQV3/" title="Typing-SIG thread">29-May-2022</a>,
|
|||
|
<a class="reference external" href="https://mail.python.org/archives/list/python-dev@python.org/thread/PLCNW2XR4OOKAKHEZQM7R2AYVYUXPZGW/" title="Python-Dev thread">12-Jul-2022</a>,
|
|||
|
<a class="reference external" href="https://discuss.python.org/t/pep-692-using-typeddict-for-more-precise-kwargs-typing/17314" title="Discourse thread">12-Jul-2022</a></dd>
|
|||
|
<dt class="field-even">Resolution<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-692-using-typeddict-for-more-precise-kwargs-typing/17314/81">Discourse 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="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
|||
|
<li><a class="reference internal" href="#specification">Specification</a><ul>
|
|||
|
<li><a class="reference internal" href="#function-calls-with-standard-dictionaries">Function calls with standard dictionaries</a></li>
|
|||
|
<li><a class="reference internal" href="#keyword-collisions">Keyword collisions</a></li>
|
|||
|
<li><a class="reference internal" href="#required-and-non-required-keys">Required and non-required keys</a></li>
|
|||
|
<li><a class="reference internal" href="#assignment">Assignment</a><ul>
|
|||
|
<li><a class="reference internal" href="#source-and-destination-contain-kwargs">Source and destination contain <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#source-contains-kwargs-and-destination-doesn-t">Source contains <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> and destination doesn’t</a></li>
|
|||
|
<li><a class="reference internal" href="#source-contains-untyped-kwargs">Source contains untyped <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#source-contains-traditionally-typed-kwargs-t">Source contains traditionally typed <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">T</span></code></a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#passing-kwargs-inside-a-function-to-another-function">Passing kwargs inside a function to another function</a></li>
|
|||
|
<li><a class="reference internal" href="#using-unpack-with-types-other-than-typeddict">Using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> with types other than <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#changes-to-unpack">Changes to <code class="docutils literal notranslate"><span class="pre">Unpack</span></code></a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#intended-usage">Intended Usage</a></li>
|
|||
|
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
|
|||
|
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
|||
|
<li><a class="reference internal" href="#typeddict-unions"><code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> unions</a></li>
|
|||
|
<li><a class="reference internal" href="#changing-the-meaning-of-kwargs-annotations">Changing the meaning of <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> annotations</a></li>
|
|||
|
<li><a class="reference internal" href="#introducing-a-new-syntax">Introducing a new syntax</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
</ul>
|
|||
|
</details></section>
|
|||
|
<div class="pep-banner canonical-typing-spec sticky-banner admonition attention">
|
|||
|
<p class="admonition-title">Attention</p>
|
|||
|
<p>This PEP is a historical document: see <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-kwargs" title="(in typing)"><span>Unpack for keyword arguments</span></a> for up-to-date specs and documentation. Canonical typing specs are maintained at the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/">typing specs site</a>; runtime typing behaviour is described in the CPython documentation.</p>
|
|||
|
<p class="close-button">×</p>
|
|||
|
<p>See the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/meta.html">typing specification update process</a> for how to propose changes to the typing spec.</p>
|
|||
|
</div>
|
|||
|
<section id="abstract">
|
|||
|
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
|||
|
<p>Currently <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> can be type hinted as long as all of the keyword
|
|||
|
arguments specified by them are of the same type. However, that behaviour can
|
|||
|
be very limiting. Therefore, in this PEP we propose a new way to enable more
|
|||
|
precise <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing. The new approach revolves around using
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> to type <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> that comprise keyword arguments of different
|
|||
|
types.</p>
|
|||
|
</section>
|
|||
|
<section id="motivation">
|
|||
|
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
|||
|
<p>Currently annotating <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> with a type <code class="docutils literal notranslate"><span class="pre">T</span></code> means that the <code class="docutils literal notranslate"><span class="pre">kwargs</span></code>
|
|||
|
type is in fact <code class="docutils literal notranslate"><span class="pre">dict[str,</span> <span class="pre">T]</span></code>. 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="o">**</span><span class="n">kwargs</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>means that all keyword arguments in <code class="docutils literal notranslate"><span class="pre">foo</span></code> are strings (i.e., <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> is
|
|||
|
of type <code class="docutils literal notranslate"><span class="pre">dict[str,</span> <span class="pre">str]</span></code>). This behaviour limits the ability to type
|
|||
|
annotate <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> only to the cases where all of them are of the same type.
|
|||
|
However, it is often the case that keyword arguments conveyed by <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>
|
|||
|
have different types that are dependent on the keyword’s name. In those cases
|
|||
|
type annotating <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> is not possible. This is especially a problem for
|
|||
|
already existing codebases where the need of refactoring the code in order to
|
|||
|
introduce proper type annotations may be considered not worth the effort. This
|
|||
|
in turn prevents the project from getting all of the benefits that type hinting
|
|||
|
can provide.</p>
|
|||
|
<p>Moreover, <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> can be used to reduce the amount of code needed in
|
|||
|
cases when there is a top-level function that is a part of a public API and it
|
|||
|
calls a bunch of helper functions, all of which expect the same keyword
|
|||
|
arguments. Unfortunately, if those helper functions were to use <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>,
|
|||
|
there is no way to properly type hint them if the keyword arguments they expect
|
|||
|
are of different types. In addition, even if the keyword arguments are of the
|
|||
|
same type, there is no way to check whether the function is being called with
|
|||
|
keyword names that it actually expects.</p>
|
|||
|
<p>As described in the <a class="reference internal" href="#intended-usage">Intended Usage</a> section,
|
|||
|
using <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> is not always the best tool for the job. Despite that, it is
|
|||
|
still a widely used pattern. As a consequence, there has been a lot of
|
|||
|
discussion around supporting more precise <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing and it became a
|
|||
|
feature that would be valuable for a large part of the Python community. This
|
|||
|
is best illustrated by the <a class="reference external" href="https://github.com/python/mypy/issues/4441">mypy GitHub issue 4441</a> which
|
|||
|
contains a lot of real world cases that could benefit from this propsal.</p>
|
|||
|
<p>One more use case worth mentioning for which <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> are also convenient,
|
|||
|
is when a function should accommodate optional keyword-only arguments that
|
|||
|
don’t have default values. A need for a pattern like that can arise when values
|
|||
|
that are usually used as defaults to indicate no user input, such as <code class="docutils literal notranslate"><span class="pre">None</span></code>,
|
|||
|
can be passed in by a user and should result in a valid, non-default behavior.
|
|||
|
For example, this issue <a class="reference external" href="https://github.com/encode/httpx/issues/1384">came up</a> in the popular <code class="docutils literal notranslate"><span class="pre">httpx</span></code> library.</p>
|
|||
|
</section>
|
|||
|
<section id="rationale">
|
|||
|
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
|||
|
<p><a class="pep reference internal" href="../pep-0589/" title="PEP 589 – TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys">PEP 589</a> introduced the <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> type constructor that supports dictionary
|
|||
|
types consisting of string keys and values of potentially different types. A
|
|||
|
function’s keyword arguments represented by a formal parameter that begins with
|
|||
|
double asterisk, such as <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>, are received as a dictionary.
|
|||
|
Additionally, such functions are often called using unpacked dictionaries to
|
|||
|
provide keyword arguments. This makes <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> a perfect candidate to be
|
|||
|
used for more precise <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing. In addition, with <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>
|
|||
|
keyword names can be taken into account during static type analysis. However,
|
|||
|
specifying <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> type with a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> means, as mentioned earlier,
|
|||
|
that each keyword argument specified by <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> is a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> itself.
|
|||
|
For instance:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Movie</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">year</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Movie</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>means that each keyword argument in <code class="docutils literal notranslate"><span class="pre">foo</span></code> is itself a <code class="docutils literal notranslate"><span class="pre">Movie</span></code> dictionary
|
|||
|
that has a <code class="docutils literal notranslate"><span class="pre">name</span></code> key with a string type value and a <code class="docutils literal notranslate"><span class="pre">year</span></code> key with an
|
|||
|
integer type value. Therefore, in order to support specifying <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> type
|
|||
|
as a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> without breaking current behaviour, a new construct has to
|
|||
|
be introduced.</p>
|
|||
|
<p>To support this use case, we propose reusing <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> which
|
|||
|
was initially introduced in <a class="pep reference internal" href="../pep-0646/" title="PEP 646 – Variadic Generics">PEP 646</a>. There are several reasons for doing so:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li>Its name is quite suitable and intuitive for the <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing use case
|
|||
|
as our intention is to “unpack” the keywords arguments from the supplied
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>.</li>
|
|||
|
<li>The current way of typing <code class="docutils literal notranslate"><span class="pre">*args</span></code> would be extended to <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>
|
|||
|
and those are supposed to behave similarly.</li>
|
|||
|
<li>There would be no need to introduce any new special forms.</li>
|
|||
|
<li>The use of <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> for the purposes described in this PEP does not
|
|||
|
interfere with the use cases described in <a class="pep reference internal" href="../pep-0646/" title="PEP 646 – Variadic Generics">PEP 646</a>.</li>
|
|||
|
</ul>
|
|||
|
</section>
|
|||
|
<section id="specification">
|
|||
|
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
|||
|
<p>With <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> we introduce a new way of annotating <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>.
|
|||
|
Continuing the previous 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="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</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>would mean that the <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> comprise two keyword arguments specified by
|
|||
|
<code class="docutils literal notranslate"><span class="pre">Movie</span></code> (i.e. a <code class="docutils literal notranslate"><span class="pre">name</span></code> keyword of type <code class="docutils literal notranslate"><span class="pre">str</span></code> and a <code class="docutils literal notranslate"><span class="pre">year</span></code> keyword of
|
|||
|
type <code class="docutils literal notranslate"><span class="pre">int</span></code>). This indicates that the function should be called as follows:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Life of Brian"</span><span class="p">,</span> <span class="s2">"year"</span><span class="p">:</span> <span class="mi">1979</span><span class="p">}</span>
|
|||
|
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="c1"># OK!</span>
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"The Meaning of Life"</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="mi">1983</span><span class="p">)</span> <span class="c1"># OK!</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> is used, type checkers treat <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> inside the
|
|||
|
function body as a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>:</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">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">assert_type</span><span class="p">(</span><span class="n">kwargs</span><span class="p">,</span> <span class="n">Movie</span><span class="p">)</span> <span class="c1"># OK!</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Using the new annotation will not have any runtime effect - it should only be
|
|||
|
taken into account by type checkers. Any mention of errors in the following
|
|||
|
sections relates to type checker errors.</p>
|
|||
|
<section id="function-calls-with-standard-dictionaries">
|
|||
|
<h3><a class="toc-backref" href="#function-calls-with-standard-dictionaries" role="doc-backlink">Function calls with standard dictionaries</a></h3>
|
|||
|
<p>Passing a dictionary of type <code class="docutils literal notranslate"><span class="pre">dict[str,</span> <span class="pre">object]</span></code> as a <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> argument
|
|||
|
to a function that has <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> annotated with <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> must generate a
|
|||
|
type checker error. On the other hand, the behaviour for functions using
|
|||
|
standard, untyped dictionaries can depend on the type checker. 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="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</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">movie</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">object</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Life of Brian"</span><span class="p">,</span> <span class="s2">"year"</span><span class="p">:</span> <span class="mi">1979</span><span class="p">}</span>
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="o">**</span><span class="n">movie</span><span class="p">)</span> <span class="c1"># WRONG! Movie is of type dict[str, object]</span>
|
|||
|
|
|||
|
<span class="n">typed_movie</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"The Meaning of Life"</span><span class="p">,</span> <span class="s2">"year"</span><span class="p">:</span> <span class="mi">1983</span><span class="p">}</span>
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="o">**</span><span class="n">typed_movie</span><span class="p">)</span> <span class="c1"># OK!</span>
|
|||
|
|
|||
|
<span class="n">another_movie</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Life of Brian"</span><span class="p">,</span> <span class="s2">"year"</span><span class="p">:</span> <span class="mi">1979</span><span class="p">}</span>
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="o">**</span><span class="n">another_movie</span><span class="p">)</span> <span class="c1"># Depends on the type checker.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="keyword-collisions">
|
|||
|
<h3><a class="toc-backref" href="#keyword-collisions" role="doc-backlink">Keyword collisions</a></h3>
|
|||
|
<p>A <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> that is used to type <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> could potentially contain
|
|||
|
keys that are already defined in the function’s signature. If the duplicate
|
|||
|
name is a standard parameter, an error should be reported by type checkers.
|
|||
|
If the duplicate name is a positional-only parameter, no errors should be
|
|||
|
generated. 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">name</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># WRONG! "name" will</span>
|
|||
|
<span class="c1"># always bind to the</span>
|
|||
|
<span class="c1"># first parameter.</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># OK! "name" is a</span>
|
|||
|
<span class="c1"># positional-only parameter,</span>
|
|||
|
<span class="c1"># so **kwargs can contain</span>
|
|||
|
<span class="c1"># a "name" keyword.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="required-and-non-required-keys">
|
|||
|
<h3><a class="toc-backref" href="#required-and-non-required-keys" role="doc-backlink">Required and non-required keys</a></h3>
|
|||
|
<p>By default all keys in a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> are required. This behaviour can be
|
|||
|
overridden by setting the dictionary’s <code class="docutils literal notranslate"><span class="pre">total</span></code> parameter as <code class="docutils literal notranslate"><span class="pre">False</span></code>.
|
|||
|
Moreover, <a class="pep reference internal" href="../pep-0655/" title="PEP 655 – Marking individual TypedDict items as required or potentially-missing">PEP 655</a> introduced new type qualifiers - <code class="docutils literal notranslate"><span class="pre">typing.Required</span></code> and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">typing.NotRequired</span></code> - that enable specifying whether a particular key is
|
|||
|
required or not:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Movie</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">title</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">year</span><span class="p">:</span> <span class="n">NotRequired</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When using a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> to type <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> all of the required and
|
|||
|
non-required keys should correspond to required and non-required function
|
|||
|
keyword parameters. Therefore, if a required key is not supported by the
|
|||
|
caller, then an error must be reported by type checkers.</p>
|
|||
|
</section>
|
|||
|
<section id="assignment">
|
|||
|
<h3><a class="toc-backref" href="#assignment" role="doc-backlink">Assignment</a></h3>
|
|||
|
<p>Assignments of a function typed with <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[Movie]</span></code> and
|
|||
|
another callable type should pass type checking only if they are compatible.
|
|||
|
This can happen for the scenarios described below.</p>
|
|||
|
<section id="source-and-destination-contain-kwargs">
|
|||
|
<h4><a class="toc-backref" href="#source-and-destination-contain-kwargs" role="doc-backlink">Source and destination contain <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code></a></h4>
|
|||
|
<p>Both destination and source functions have a <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[TypedDict]</span></code>
|
|||
|
parameter and the destination function’s <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> is assignable to the
|
|||
|
source function’s <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> and the rest of the parameters are
|
|||
|
compatible:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Animal</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Dog</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
|
|||
|
<span class="n">breed</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">accept_animal</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Animal</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
<span class="k">def</span> <span class="nf">accept_dog</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Dog</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="n">accept_dog</span> <span class="o">=</span> <span class="n">accept_animal</span> <span class="c1"># OK! Expression of type Dog can be</span>
|
|||
|
<span class="c1"># assigned to a variable of type Animal.</span>
|
|||
|
|
|||
|
<span class="n">accept_animal</span> <span class="o">=</span> <span class="n">accept_dog</span> <span class="c1"># WRONG! Expression of type Animal</span>
|
|||
|
<span class="c1"># cannot be assigned to a variable of type Dog.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="source-contains-kwargs-and-destination-doesn-t">
|
|||
|
<span id="pep-692-assignment-dest-no-kwargs"></span><h4><a class="toc-backref" href="#source-contains-kwargs-and-destination-doesn-t" role="doc-backlink">Source contains <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> and destination doesn’t</a></h4>
|
|||
|
<p>The destination callable doesn’t contain <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>, the source callable
|
|||
|
contains <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[TypedDict]</span></code> and the destination function’s keyword
|
|||
|
arguments are assignable to the corresponding keys in source function’s
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>. Moreover, not required keys should correspond to optional
|
|||
|
function arguments, whereas required keys should correspond to required
|
|||
|
function arguments. Again, the rest of the parameters have to be compatible.
|
|||
|
Continuing the previous example:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Example</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">animal</span><span class="p">:</span> <span class="n">Animal</span>
|
|||
|
<span class="n">string</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">number</span><span class="p">:</span> <span class="n">NotRequired</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">src</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Example</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
<span class="k">def</span> <span class="nf">dest</span><span class="p">(</span><span class="o">*</span><span class="p">,</span> <span class="n">animal</span><span class="p">:</span> <span class="n">Dog</span><span class="p">,</span> <span class="n">string</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">number</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="o">...</span><span class="p">):</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="n">dest</span> <span class="o">=</span> <span class="n">src</span> <span class="c1"># OK!</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>It is worth pointing out that the destination function’s parameters that are to
|
|||
|
be compatible with the keys and values from the <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> must be keyword
|
|||
|
only:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">dest</span><span class="p">(</span><span class="n">dog</span><span class="p">:</span> <span class="n">Dog</span><span class="p">,</span> <span class="n">string</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">number</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="o">...</span><span class="p">):</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="n">dog</span><span class="p">:</span> <span class="n">Dog</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Daisy"</span><span class="p">,</span> <span class="s2">"breed"</span><span class="p">:</span> <span class="s2">"labrador"</span><span class="p">}</span>
|
|||
|
|
|||
|
<span class="n">dest</span><span class="p">(</span><span class="n">dog</span><span class="p">,</span> <span class="s2">"some string"</span><span class="p">)</span> <span class="c1"># OK!</span>
|
|||
|
|
|||
|
<span class="n">dest</span> <span class="o">=</span> <span class="n">src</span> <span class="c1"># Type checker error!</span>
|
|||
|
<span class="n">dest</span><span class="p">(</span><span class="n">dog</span><span class="p">,</span> <span class="s2">"some string"</span><span class="p">)</span> <span class="c1"># The same call fails at</span>
|
|||
|
<span class="c1"># runtime now because 'src' expects</span>
|
|||
|
<span class="c1"># keyword arguments.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The reverse situation where the destination callable contains
|
|||
|
<code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[TypedDict]</span></code> and the source callable doesn’t contain
|
|||
|
<code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> should be disallowed. This is because, we cannot be sure that
|
|||
|
additional keyword arguments are not being passed in when an instance of a
|
|||
|
subclass had been assigned to a variable with a base class type and then
|
|||
|
unpacked in the destination callable invocation:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">dest</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Animal</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
<span class="k">def</span> <span class="nf">src</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">dog</span><span class="p">:</span> <span class="n">Dog</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Daisy"</span><span class="p">,</span> <span class="s2">"breed"</span><span class="p">:</span> <span class="s2">"Labrador"</span><span class="p">}</span>
|
|||
|
<span class="n">animal</span><span class="p">:</span> <span class="n">Animal</span> <span class="o">=</span> <span class="n">dog</span>
|
|||
|
|
|||
|
<span class="n">dest</span> <span class="o">=</span> <span class="n">src</span> <span class="c1"># WRONG!</span>
|
|||
|
<span class="n">dest</span><span class="p">(</span><span class="o">**</span><span class="n">animal</span><span class="p">)</span> <span class="c1"># Fails at runtime.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Similar situation can happen even without inheritance as compatibility
|
|||
|
between <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>s is based on structural subtyping.</p>
|
|||
|
</section>
|
|||
|
<section id="source-contains-untyped-kwargs">
|
|||
|
<h4><a class="toc-backref" href="#source-contains-untyped-kwargs" role="doc-backlink">Source contains untyped <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code></a></h4>
|
|||
|
<p>The destination callable contains <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[TypedDict]</span></code> and the
|
|||
|
source callable contains untyped <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">src</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> <span class="o">...</span>
|
|||
|
<span class="k">def</span> <span class="nf">dest</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="n">dest</span> <span class="o">=</span> <span class="n">src</span> <span class="c1"># OK!</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="source-contains-traditionally-typed-kwargs-t">
|
|||
|
<h4><a class="toc-backref" href="#source-contains-traditionally-typed-kwargs-t" role="doc-backlink">Source contains traditionally typed <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">T</span></code></a></h4>
|
|||
|
<p>The destination callable contains <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[TypedDict]</span></code>, the source
|
|||
|
callable contains traditionally typed <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">T</span></code> and each of the
|
|||
|
destination function <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>’s fields is assignable to a variable of
|
|||
|
type <code class="docutils literal notranslate"><span class="pre">T</span></code>:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Vehicle</span><span class="p">:</span>
|
|||
|
<span class="o">...</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Car</span><span class="p">(</span><span class="n">Vehicle</span><span class="p">):</span>
|
|||
|
<span class="o">...</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Motorcycle</span><span class="p">(</span><span class="n">Vehicle</span><span class="p">):</span>
|
|||
|
<span class="o">...</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Vehicles</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">car</span><span class="p">:</span> <span class="n">Car</span>
|
|||
|
<span class="n">moto</span><span class="p">:</span> <span class="n">Motorcycle</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">dest</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Vehicles</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
<span class="k">def</span> <span class="nf">src</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Vehicle</span><span class="p">):</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="n">dest</span> <span class="o">=</span> <span class="n">src</span> <span class="c1"># OK!</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>On the other hand, if the destination callable contains either untyped or
|
|||
|
traditionally typed <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">T</span></code> and the source callable is typed using
|
|||
|
<code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Unpack[TypedDict]</span></code> then an error should be generated, because
|
|||
|
traditionally typed <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> aren’t checked for keyword names.</p>
|
|||
|
<p>To summarize, function parameters should behave contravariantly and function
|
|||
|
return types should behave covariantly.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="passing-kwargs-inside-a-function-to-another-function">
|
|||
|
<h3><a class="toc-backref" href="#passing-kwargs-inside-a-function-to-another-function" role="doc-backlink">Passing kwargs inside a function to another function</a></h3>
|
|||
|
<p><a class="reference external" href="PEP692assignmentdestnokwargs">A previous point</a>
|
|||
|
mentions the problem of possibly passing additional keyword arguments by
|
|||
|
assigning a subclass instance to a variable that has a base class type. Let’s
|
|||
|
consider the following example:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Animal</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Dog</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
|
|||
|
<span class="n">breed</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">takes_name</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">dog</span><span class="p">:</span> <span class="n">Dog</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Daisy"</span><span class="p">,</span> <span class="s2">"breed"</span><span class="p">:</span> <span class="s2">"Labrador"</span><span class="p">}</span>
|
|||
|
<span class="n">animal</span><span class="p">:</span> <span class="n">Animal</span> <span class="o">=</span> <span class="n">dog</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Animal</span><span class="p">]):</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">kwargs</span><span class="p">[</span><span class="s2">"name"</span><span class="p">]</span><span class="o">.</span><span class="n">capitalize</span><span class="p">())</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">bar</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Animal</span><span class="p">]):</span>
|
|||
|
<span class="n">takes_name</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">baz</span><span class="p">(</span><span class="n">animal</span><span class="p">:</span> <span class="n">Animal</span><span class="p">):</span>
|
|||
|
<span class="n">takes_name</span><span class="p">(</span><span class="o">**</span><span class="n">animal</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">spam</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Animal</span><span class="p">]):</span>
|
|||
|
<span class="n">baz</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="o">**</span><span class="n">animal</span><span class="p">)</span> <span class="c1"># OK! foo only expects and uses keywords of 'Animal'.</span>
|
|||
|
|
|||
|
<span class="n">bar</span><span class="p">(</span><span class="o">**</span><span class="n">animal</span><span class="p">)</span> <span class="c1"># WRONG! This will fail at runtime because 'breed' keyword</span>
|
|||
|
<span class="c1"># will be passed to 'takes_name' as well.</span>
|
|||
|
|
|||
|
<span class="n">spam</span><span class="p">(</span><span class="o">**</span><span class="n">animal</span><span class="p">)</span> <span class="c1"># WRONG! Again, 'breed' keyword will be eventually passed</span>
|
|||
|
<span class="c1"># to 'takes_name'.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>In the example above, the call to <code class="docutils literal notranslate"><span class="pre">foo</span></code> will not cause any issues at
|
|||
|
runtime. Even though <code class="docutils literal notranslate"><span class="pre">foo</span></code> expects <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> of type <code class="docutils literal notranslate"><span class="pre">Animal</span></code> it doesn’t
|
|||
|
matter if it receives additional arguments because it only reads and uses what
|
|||
|
it needs completely ignoring any additional values.</p>
|
|||
|
<p>The calls to <code class="docutils literal notranslate"><span class="pre">bar</span></code> and <code class="docutils literal notranslate"><span class="pre">spam</span></code> will fail because an unexpected keyword
|
|||
|
argument will be passed to the <code class="docutils literal notranslate"><span class="pre">takes_name</span></code> function.</p>
|
|||
|
<p>Therefore, <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> hinted with an unpacked <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> can only be passed
|
|||
|
to another function if the function to which unpacked kwargs are being passed
|
|||
|
to has <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> in its signature as well, because then additional keywords
|
|||
|
would not cause errors at runtime during function invocation. Otherwise, the
|
|||
|
type checker should generate an error.</p>
|
|||
|
<p>In cases similar to the <code class="docutils literal notranslate"><span class="pre">bar</span></code> function above the problem could be worked
|
|||
|
around by explicitly dereferencing desired fields and using them as arguments
|
|||
|
to perform the function call:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">bar</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Animal</span><span class="p">]):</span>
|
|||
|
<span class="n">name</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"name"</span><span class="p">]</span>
|
|||
|
<span class="n">takes_name</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="using-unpack-with-types-other-than-typeddict">
|
|||
|
<h3><a class="toc-backref" href="#using-unpack-with-types-other-than-typeddict" role="doc-backlink">Using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> with types other than <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code></a></h3>
|
|||
|
<p>As described in the <a class="reference internal" href="#rationale">Rationale</a> section,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> is the most natural candidate for typing <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>.
|
|||
|
Therefore, in the context of typing <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>, using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> with types
|
|||
|
other than <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> should not be allowed and type checkers should
|
|||
|
generate errors in such cases.</p>
|
|||
|
</section>
|
|||
|
<section id="changes-to-unpack">
|
|||
|
<h3><a class="toc-backref" href="#changes-to-unpack" role="doc-backlink">Changes to <code class="docutils literal notranslate"><span class="pre">Unpack</span></code></a></h3>
|
|||
|
<p>Currently using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> in the context of
|
|||
|
typing is interchangeable with using the asterisk syntax:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">]</span>
|
|||
|
<span class="go">*<class '__main__.Movie'></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Therefore, in order to be compatible with the new use case, <code class="docutils literal notranslate"><span class="pre">Unpack</span></code>’s
|
|||
|
<code class="docutils literal notranslate"><span class="pre">repr</span></code> should be changed to simply <code class="docutils literal notranslate"><span class="pre">Unpack[T]</span></code>.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="intended-usage">
|
|||
|
<h2><a class="toc-backref" href="#intended-usage" role="doc-backlink">Intended Usage</a></h2>
|
|||
|
<p>The intended use cases for this proposal are described in the
|
|||
|
<a class="reference internal" href="#motivation">Motivation</a> section. In summary, more precise <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing
|
|||
|
can bring benefits to already existing codebases that decided to use
|
|||
|
<code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> initially, but now are mature enough to use a stricter contract
|
|||
|
via type hints. Using <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> can also help in reducing code duplication
|
|||
|
and the amount of copy-pasting needed when there is a bunch of functions that
|
|||
|
require the same set of keyword arguments. Finally, <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> are useful for
|
|||
|
cases when a function needs to facilitate optional keyword arguments that don’t
|
|||
|
have obvious default values.</p>
|
|||
|
<p>However, it has to be pointed out that in some cases there are better tools
|
|||
|
for the job than using <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> to type <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> as proposed in this
|
|||
|
PEP. For example, when writing new code if all the keyword arguments are
|
|||
|
required or have default values then writing everything explicitly is better
|
|||
|
than using <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> and a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>:</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">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">year</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span> <span class="o">...</span> <span class="c1"># Preferred way.</span>
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Similarly, when type hinting third party libraries via stubs it is again better
|
|||
|
to state the function signature explicitly - this is the only way to type such
|
|||
|
a function if it has default arguments. Another issue that may arise in this
|
|||
|
case when trying to type hint the function with a <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> is that some
|
|||
|
standard function parameters may be treated as keyword only:</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">name</span><span class="p">,</span> <span class="n">year</span><span class="p">):</span> <span class="o">...</span> <span class="c1"># Function in a third party library.</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">]):</span> <span class="o">...</span> <span class="c1"># Function signature in a stub file.</span>
|
|||
|
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="s2">"Life of Brian"</span><span class="p">,</span> <span class="mi">1979</span><span class="p">)</span> <span class="c1"># This would be now failing type</span>
|
|||
|
<span class="c1"># checking but is fine.</span>
|
|||
|
|
|||
|
<span class="n">foo</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">"Life of Brian"</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="mi">1979</span><span class="p">)</span> <span class="c1"># This would be the only way to call</span>
|
|||
|
<span class="c1"># the function now that passes type</span>
|
|||
|
<span class="c1"># checking.</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Therefore, in this case it is again preferred to type hint such function
|
|||
|
explicitly as:</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">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">year</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span> <span class="o">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Also, for the benefit of IDEs and documentation pages, functions that are part
|
|||
|
of the public API should prefer explicit keyword parameters whenever possible.</p>
|
|||
|
</section>
|
|||
|
<section id="how-to-teach-this">
|
|||
|
<h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2>
|
|||
|
<p>This PEP could be linked in the <code class="docutils literal notranslate"><span class="pre">typing</span></code> module’s documentation. Moreover, a
|
|||
|
new section on using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> could be added to the aforementioned docs.
|
|||
|
Similar sections could be also added to the
|
|||
|
<a class="reference external" href="https://mypy.readthedocs.io/">mypy documentation</a> and the
|
|||
|
<a class="reference external" href="https://typing.readthedocs.io/">typing RTD documentation</a>.</p>
|
|||
|
</section>
|
|||
|
<section id="reference-implementation">
|
|||
|
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
|
|||
|
<p>The <a class="reference external" href="https://github.com/python/mypy">mypy type checker</a> already
|
|||
|
<a class="reference external" href="https://github.com/python/mypy/pull/13471">supports</a> more precise
|
|||
|
<code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code>.</p>
|
|||
|
<p><a class="reference external" href="https://github.com/microsoft/pyright">Pyright type checker</a> also
|
|||
|
<a class="reference external" href="https://github.com/microsoft/pyright/commit/5bee749eb171979e3f526cd8e5bf66b00593378a">provides provisional support</a>
|
|||
|
for <a class="reference external" href="https://github.com/microsoft/pyright/issues/3002">this feature</a>.</p>
|
|||
|
</section>
|
|||
|
<section id="rejected-ideas">
|
|||
|
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
|
|||
|
<section id="typeddict-unions">
|
|||
|
<h3><a class="toc-backref" href="#typeddict-unions" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> unions</a></h3>
|
|||
|
<p>It is possible to create unions of typed dictionaries. However, supporting
|
|||
|
typing <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> with a union of typed dicts would greatly increase the
|
|||
|
complexity of the implementation of this PEP and there seems to be no
|
|||
|
compelling use case to justify the support for this. Therefore, using unions of
|
|||
|
typed dictionaries to type <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> as described in the context of this PEP
|
|||
|
can result in an error:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">genre</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">pages</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="n">TypedDictUnion</span> <span class="o">=</span> <span class="n">Movie</span> <span class="o">|</span> <span class="n">Book</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">TypedDictUnion</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span> <span class="c1"># WRONG! Unsupported use</span>
|
|||
|
<span class="c1"># of a union of</span>
|
|||
|
<span class="c1"># TypedDicts to type</span>
|
|||
|
<span class="c1"># **kwargs</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Instead, a function that expects a union of <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>s can be
|
|||
|
overloaded:</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">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="nd">@overload</span>
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Book</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="changing-the-meaning-of-kwargs-annotations">
|
|||
|
<h3><a class="toc-backref" href="#changing-the-meaning-of-kwargs-annotations" role="doc-backlink">Changing the meaning of <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> annotations</a></h3>
|
|||
|
<p>One way to achieve the purpose of this PEP would be to change the
|
|||
|
meaning of <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> annotations, so that the annotations would
|
|||
|
apply to the entire <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> dict, not to individual elements.
|
|||
|
For consistency, we would have to make an analogous change to <code class="docutils literal notranslate"><span class="pre">*args</span></code>
|
|||
|
annotations.</p>
|
|||
|
<p>This idea was discussed in a meeting of the typing community, and the
|
|||
|
consensus was that the change would not be worth the cost. There is no
|
|||
|
clear migration path, the current meaning of <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>
|
|||
|
annotations is well-established in the ecosystem, and type checkers
|
|||
|
would have to introduce new errors for code that is currently legal.</p>
|
|||
|
</section>
|
|||
|
<section id="introducing-a-new-syntax">
|
|||
|
<h3><a class="toc-backref" href="#introducing-a-new-syntax" role="doc-backlink">Introducing a new syntax</a></h3>
|
|||
|
<p>In the previous versions of this PEP, using a double asterisk syntax was
|
|||
|
proposed to support more precise <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> typing. Using this syntax,
|
|||
|
functions could be annotated as follows:</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">kwargs</span><span class="p">:</span> <span class="o">**</span><span class="n">Movie</span><span class="p">):</span> <span class="o">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Which would have the same meaning as:</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">kwargs</span><span class="p">:</span> <span class="n">Unpack</span><span class="p">[</span><span class="n">Movie</span><span class="p">]):</span> <span class="o">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This greatly increased the scope of the PEP, as it would require a grammar
|
|||
|
change and adding a new dunder for the <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> special form. At the same
|
|||
|
the justification for introducing a new syntax was not strong enough and
|
|||
|
became a blocker for the whole PEP. Therefore, we decided to abandon the idea
|
|||
|
of introducing a new syntax as a part of this PEP and may propose it again in a
|
|||
|
separate one.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="copyright">
|
|||
|
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
|||
|
<p>This document is placed in the public domain or under the
|
|||
|
CC0-1.0-Universal license, whichever is more permissive.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<hr class="docutils" />
|
|||
|
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0692.rst">https://github.com/python/peps/blob/main/peps/pep-0692.rst</a></p>
|
|||
|
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0692.rst">2024-02-16 16:12:21 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="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#rationale">Rationale</a></li>
|
|||
|
<li><a class="reference internal" href="#specification">Specification</a><ul>
|
|||
|
<li><a class="reference internal" href="#function-calls-with-standard-dictionaries">Function calls with standard dictionaries</a></li>
|
|||
|
<li><a class="reference internal" href="#keyword-collisions">Keyword collisions</a></li>
|
|||
|
<li><a class="reference internal" href="#required-and-non-required-keys">Required and non-required keys</a></li>
|
|||
|
<li><a class="reference internal" href="#assignment">Assignment</a><ul>
|
|||
|
<li><a class="reference internal" href="#source-and-destination-contain-kwargs">Source and destination contain <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#source-contains-kwargs-and-destination-doesn-t">Source contains <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> and destination doesn’t</a></li>
|
|||
|
<li><a class="reference internal" href="#source-contains-untyped-kwargs">Source contains untyped <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#source-contains-traditionally-typed-kwargs-t">Source contains traditionally typed <code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">T</span></code></a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#passing-kwargs-inside-a-function-to-another-function">Passing kwargs inside a function to another function</a></li>
|
|||
|
<li><a class="reference internal" href="#using-unpack-with-types-other-than-typeddict">Using <code class="docutils literal notranslate"><span class="pre">Unpack</span></code> with types other than <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#changes-to-unpack">Changes to <code class="docutils literal notranslate"><span class="pre">Unpack</span></code></a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#intended-usage">Intended Usage</a></li>
|
|||
|
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
|
|||
|
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
|||
|
<li><a class="reference internal" href="#typeddict-unions"><code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> unions</a></li>
|
|||
|
<li><a class="reference internal" href="#changing-the-meaning-of-kwargs-annotations">Changing the meaning of <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> annotations</a></li>
|
|||
|
<li><a class="reference internal" href="#introducing-a-new-syntax">Introducing a new syntax</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<br>
|
|||
|
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0692.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>
|