727 lines
76 KiB
HTML
727 lines
76 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 636 – Structural Pattern Matching: Tutorial | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0636/">
|
||
<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 636 – Structural Pattern Matching: Tutorial | peps.python.org'>
|
||
<meta property="og:description" content="This PEP is a tutorial for the pattern matching introduced by PEP 634.">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0636/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="This PEP is a tutorial for the pattern matching introduced by PEP 634.">
|
||
<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 636</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 636 – Structural Pattern Matching: Tutorial</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Daniel F Moisset <dfmoisset at gmail.com></dd>
|
||
<dt class="field-even">Sponsor<span class="colon">:</span></dt>
|
||
<dd class="field-even">Guido van Rossum <guido at python.org></dd>
|
||
<dt class="field-odd">BDFL-Delegate<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><p></p></dd>
|
||
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/python-dev@python.org/">Python-Dev list</a></dd>
|
||
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
||
<dt class="field-even">Type<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
|
||
<dt class="field-odd">Created<span class="colon">:</span></dt>
|
||
<dd class="field-odd">12-Sep-2020</dd>
|
||
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-even">3.10</dd>
|
||
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-odd">22-Oct-2020, 08-Feb-2021</dd>
|
||
<dt class="field-even">Resolution<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/python-committers@python.org/message/SQC2FTLFV5A7DV7RCEAR2I2IKJKGK7W3">Python-Committers 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="#tutorial">Tutorial</a><ul>
|
||
<li><a class="reference internal" href="#matching-sequences">Matching sequences</a></li>
|
||
<li><a class="reference internal" href="#matching-multiple-patterns">Matching multiple patterns</a></li>
|
||
<li><a class="reference internal" href="#matching-specific-values">Matching specific values</a></li>
|
||
<li><a class="reference internal" href="#matching-multiple-values">Matching multiple values</a></li>
|
||
<li><a class="reference internal" href="#adding-a-wildcard">Adding a wildcard</a></li>
|
||
<li><a class="reference internal" href="#composing-patterns">Composing patterns</a></li>
|
||
<li><a class="reference internal" href="#or-patterns">Or patterns</a></li>
|
||
<li><a class="reference internal" href="#capturing-matched-sub-patterns">Capturing matched sub-patterns</a></li>
|
||
<li><a class="reference internal" href="#adding-conditions-to-patterns">Adding conditions to patterns</a></li>
|
||
<li><a class="reference internal" href="#adding-a-ui-matching-objects">Adding a UI: Matching objects</a></li>
|
||
<li><a class="reference internal" href="#matching-positional-attributes">Matching positional attributes</a></li>
|
||
<li><a class="reference internal" href="#matching-against-constants-and-enums">Matching against constants and enums</a></li>
|
||
<li><a class="reference internal" href="#going-to-the-cloud-mappings">Going to the cloud: Mappings</a></li>
|
||
<li><a class="reference internal" href="#matching-builtin-classes">Matching builtin classes</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#appendix-a-quick-intro">Appendix A – Quick Intro</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>This PEP is a tutorial for the pattern matching introduced by <a class="pep reference internal" href="../pep-0634/" title="PEP 634 – Structural Pattern Matching: Specification">PEP 634</a>.</p>
|
||
<p><a class="pep reference internal" href="../pep-0622/" title="PEP 622 – Structural Pattern Matching">PEP 622</a> proposed syntax for pattern matching, which received detailed discussion
|
||
both from the community and the Steering Council. A frequent concern was
|
||
about how easy it would be to explain (and learn) this feature. This PEP
|
||
addresses that concern providing the kind of document which developers could use
|
||
to learn about pattern matching in Python.</p>
|
||
<p>This is considered supporting material for <a class="pep reference internal" href="../pep-0634/" title="PEP 634 – Structural Pattern Matching: Specification">PEP 634</a> (the technical specification
|
||
for pattern matching) and <a class="pep reference internal" href="../pep-0635/" title="PEP 635 – Structural Pattern Matching: Motivation and Rationale">PEP 635</a> (the motivation and rationale for having pattern
|
||
matching and design considerations).</p>
|
||
<p>For readers who are looking more for a quick review than for a tutorial,
|
||
see <a class="reference internal" href="#pep-636-appendix-a">Appendix A</a>.</p>
|
||
</section>
|
||
<section id="tutorial">
|
||
<h2><a class="toc-backref" href="#tutorial" role="doc-backlink">Tutorial</a></h2>
|
||
<p>As an example to motivate this tutorial, you will be writing a text adventure. That is
|
||
a form of interactive fiction where the user enters text commands to interact with a
|
||
fictional world and receives text descriptions of what happens. Commands will be
|
||
simplified forms of natural language like <code class="docutils literal notranslate"><span class="pre">get</span> <span class="pre">sword</span></code>, <code class="docutils literal notranslate"><span class="pre">attack</span> <span class="pre">dragon</span></code>, <code class="docutils literal notranslate"><span class="pre">go</span> <span class="pre">north</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">enter</span> <span class="pre">shop</span></code> or <code class="docutils literal notranslate"><span class="pre">buy</span> <span class="pre">cheese</span></code>.</p>
|
||
<section id="matching-sequences">
|
||
<h3><a class="toc-backref" href="#matching-sequences" role="doc-backlink">Matching sequences</a></h3>
|
||
<p>Your main loop will need to get input from the user and split it into words, let’s say
|
||
a list of strings like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">command</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">"What are you doing next? "</span><span class="p">)</span>
|
||
<span class="c1"># analyze the result of command.split()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The next step is to interpret the words. Most of our commands will have two words: an
|
||
action and an object. So you may be tempted to do the following:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">action</span><span class="p">,</span> <span class="n">obj</span><span class="p">]</span> <span class="o">=</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
|
||
<span class="o">...</span> <span class="c1"># interpret action, obj</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The problem with that line of code is that it’s missing something: what if the user
|
||
types more or fewer than 2 words? To prevent this problem you can either check the length
|
||
of the list of words, or capture the <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> that the statement above would raise.</p>
|
||
<p>You can use a matching statement instead:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="n">action</span><span class="p">,</span> <span class="n">obj</span><span class="p">]:</span>
|
||
<span class="o">...</span> <span class="c1"># interpret action, obj</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The match statement evaluates the <strong>“subject”</strong> (the value after the <code class="docutils literal notranslate"><span class="pre">match</span></code>
|
||
keyword), and checks it against the <strong>pattern</strong> (the code next to <code class="docutils literal notranslate"><span class="pre">case</span></code>). A pattern
|
||
is able to do two different things:</p>
|
||
<ul class="simple">
|
||
<li>Verify that the subject has certain structure. In your case, the <code class="docutils literal notranslate"><span class="pre">[action,</span> <span class="pre">obj]</span></code>
|
||
pattern matches any sequence of exactly two elements. This is called <strong>matching</strong></li>
|
||
<li>It will bind some names in the pattern to component elements of your subject. In
|
||
this case, if the list has two elements, it will bind <code class="docutils literal notranslate"><span class="pre">action</span> <span class="pre">=</span> <span class="pre">subject[0]</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">subject[1]</span></code>.</li>
|
||
</ul>
|
||
<p>If there’s a match, the statements inside the case block will be executed with the
|
||
bound variables. If there’s no match, nothing happens and the statement after
|
||
<code class="docutils literal notranslate"><span class="pre">match</span></code> is executed next.</p>
|
||
<p>Note that, in a similar way to unpacking assignments, you can use either parenthesis,
|
||
brackets, or just comma separation as synonyms. So you could write <code class="docutils literal notranslate"><span class="pre">case</span> <span class="pre">action,</span> <span class="pre">obj</span></code>
|
||
or <code class="docutils literal notranslate"><span class="pre">case</span> <span class="pre">(action,</span> <span class="pre">obj)</span></code> with the same meaning. All forms will match any sequence (for
|
||
example lists or tuples).</p>
|
||
</section>
|
||
<section id="matching-multiple-patterns">
|
||
<h3><a class="toc-backref" href="#matching-multiple-patterns" role="doc-backlink">Matching multiple patterns</a></h3>
|
||
<p>Even if most commands have the action/object form, you might want to have user commands
|
||
of different lengths. For example, you might want to add single verbs with no object like
|
||
<code class="docutils literal notranslate"><span class="pre">look</span></code> or <code class="docutils literal notranslate"><span class="pre">quit</span></code>. A match statement can (and is likely to) have more than one
|
||
<code class="docutils literal notranslate"><span class="pre">case</span></code>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="n">action</span><span class="p">]:</span>
|
||
<span class="o">...</span> <span class="c1"># interpret single-verb action</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="n">action</span><span class="p">,</span> <span class="n">obj</span><span class="p">]:</span>
|
||
<span class="o">...</span> <span class="c1"># interpret action, obj</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The match statement will check patterns from top to bottom. If the pattern doesn’t
|
||
match the subject, the next pattern will be tried. However, once the <em>first</em>
|
||
matching pattern is found, the body of that case is executed, and all further
|
||
cases are ignored. This is similar to the way that an <code class="docutils literal notranslate"><span class="pre">if/elif/elif/...</span></code>
|
||
statement works.</p>
|
||
</section>
|
||
<section id="matching-specific-values">
|
||
<h3><a class="toc-backref" href="#matching-specific-values" role="doc-backlink">Matching specific values</a></h3>
|
||
<p>Your code still needs to look at the specific actions and conditionally execute
|
||
different logic depending on the specific action (e.g., <code class="docutils literal notranslate"><span class="pre">quit</span></code>, <code class="docutils literal notranslate"><span class="pre">attack</span></code>, or <code class="docutils literal notranslate"><span class="pre">buy</span></code>).
|
||
You could do that using a chain of <code class="docutils literal notranslate"><span class="pre">if/elif/elif/...</span></code>, or using a dictionary of
|
||
functions, but here we’ll leverage pattern matching to solve that task. Instead of a
|
||
variable, you can use literal values in patterns (like <code class="docutils literal notranslate"><span class="pre">"quit"</span></code>, <code class="docutils literal notranslate"><span class="pre">42</span></code>, or <code class="docutils literal notranslate"><span class="pre">None</span></code>).
|
||
This allows you to write:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"quit"</span><span class="p">]:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Goodbye!"</span><span class="p">)</span>
|
||
<span class="n">quit_game</span><span class="p">()</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"look"</span><span class="p">]:</span>
|
||
<span class="n">current_room</span><span class="o">.</span><span class="n">describe</span><span class="p">()</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"get"</span><span class="p">,</span> <span class="n">obj</span><span class="p">]:</span>
|
||
<span class="n">character</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">current_room</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="n">direction</span><span class="p">]:</span>
|
||
<span class="n">current_room</span> <span class="o">=</span> <span class="n">current_room</span><span class="o">.</span><span class="n">neighbor</span><span class="p">(</span><span class="n">direction</span><span class="p">)</span>
|
||
<span class="c1"># The rest of your commands go here</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A pattern like <code class="docutils literal notranslate"><span class="pre">["get",</span> <span class="pre">obj]</span></code> will match only 2-element sequences that have a first
|
||
element equal to <code class="docutils literal notranslate"><span class="pre">"get"</span></code>. It will also bind <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">subject[1]</span></code>.</p>
|
||
<p>As you can see in the <code class="docutils literal notranslate"><span class="pre">go</span></code> case, we also can use different variable names in
|
||
different patterns.</p>
|
||
<p>Literal values are compared with the <code class="docutils literal notranslate"><span class="pre">==</span></code> operator except for the constants <code class="docutils literal notranslate"><span class="pre">True</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">None</span></code> which are compared with the <code class="docutils literal notranslate"><span class="pre">is</span></code> operator.</p>
|
||
</section>
|
||
<section id="matching-multiple-values">
|
||
<h3><a class="toc-backref" href="#matching-multiple-values" role="doc-backlink">Matching multiple values</a></h3>
|
||
<p>A player may be able to drop multiple items by using a series of commands
|
||
<code class="docutils literal notranslate"><span class="pre">drop</span> <span class="pre">key</span></code>, <code class="docutils literal notranslate"><span class="pre">drop</span> <span class="pre">sword</span></code>, <code class="docutils literal notranslate"><span class="pre">drop</span> <span class="pre">cheese</span></code>. This interface might be cumbersome, and
|
||
you might like to allow dropping multiple items in a single command, like
|
||
<code class="docutils literal notranslate"><span class="pre">drop</span> <span class="pre">key</span> <span class="pre">sword</span> <span class="pre">cheese</span></code>. In this case you don’t know beforehand how many words will
|
||
be in the command, but you can use extended unpacking in patterns in the same way that
|
||
they are allowed in assignments:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"drop"</span><span class="p">,</span> <span class="o">*</span><span class="n">objects</span><span class="p">]:</span>
|
||
<span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">objects</span><span class="p">:</span>
|
||
<span class="n">character</span><span class="o">.</span><span class="n">drop</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">current_room</span><span class="p">)</span>
|
||
<span class="c1"># The rest of your commands go here</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This will match any sequences having “drop” as its first elements. All remaining
|
||
elements will be captured in a <code class="docutils literal notranslate"><span class="pre">list</span></code> object which will be bound to the <code class="docutils literal notranslate"><span class="pre">objects</span></code>
|
||
variable.</p>
|
||
<p>This syntax has similar restrictions as sequence unpacking: you can not have more than one
|
||
starred name in a pattern.</p>
|
||
</section>
|
||
<section id="adding-a-wildcard">
|
||
<h3><a class="toc-backref" href="#adding-a-wildcard" role="doc-backlink">Adding a wildcard</a></h3>
|
||
<p>You may want to print an error message saying that the command wasn’t recognized when
|
||
all the patterns fail. You could use the feature we just learned and write
|
||
<code class="docutils literal notranslate"><span class="pre">case</span> <span class="pre">[*ignored_words]</span></code> as your last pattern. There’s however a much simpler way:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"quit"</span><span class="p">]:</span> <span class="o">...</span> <span class="c1"># Code omitted for brevity</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="n">direction</span><span class="p">]:</span> <span class="o">...</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"drop"</span><span class="p">,</span> <span class="o">*</span><span class="n">objects</span><span class="p">]:</span> <span class="o">...</span>
|
||
<span class="o">...</span> <span class="c1"># Other cases</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Sorry, I couldn't understand </span><span class="si">{</span><span class="n">command</span><span class="si">!r}</span><span class="s2">"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This special pattern which is written <code class="docutils literal notranslate"><span class="pre">_</span></code> (and called wildcard) always
|
||
matches but it doesn’t bind any variables.</p>
|
||
<p>Note that this will match any object, not just sequences. As such, it only makes
|
||
sense to have it by itself as the last pattern (to prevent errors, Python will stop
|
||
you from using it before).</p>
|
||
</section>
|
||
<section id="composing-patterns">
|
||
<h3><a class="toc-backref" href="#composing-patterns" role="doc-backlink">Composing patterns</a></h3>
|
||
<p>This is a good moment to step back from the examples and understand how the patterns
|
||
that you have been using are built. Patterns can be nested within each other, and we
|
||
have been doing that implicitly in the examples above.</p>
|
||
<p>There are some “simple” patterns (“simple” here meaning that they do not contain other
|
||
patterns) that we’ve seen:</p>
|
||
<ul class="simple">
|
||
<li><strong>Capture patterns</strong> (stand-alone names like <code class="docutils literal notranslate"><span class="pre">direction</span></code>, <code class="docutils literal notranslate"><span class="pre">action</span></code>, <code class="docutils literal notranslate"><span class="pre">objects</span></code>). We
|
||
never discussed these separately, but used them as part of other patterns.</li>
|
||
<li><strong>Literal patterns</strong> (string literals, number literals, <code class="docutils literal notranslate"><span class="pre">True</span></code>, <code class="docutils literal notranslate"><span class="pre">False</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code>)</li>
|
||
<li>The <strong>wildcard pattern</strong> <code class="docutils literal notranslate"><span class="pre">_</span></code></li>
|
||
</ul>
|
||
<p>Until now, the only non-simple pattern we have experimented with is the sequence pattern.
|
||
Each element in a sequence pattern can in fact be
|
||
any other pattern. This means that you could write a pattern like
|
||
<code class="docutils literal notranslate"><span class="pre">["first",</span> <span class="pre">(left,</span> <span class="pre">right),</span> <span class="pre">_,</span> <span class="pre">*rest]</span></code>. This will match subjects which are a sequence of at
|
||
least three elements, where the first one is equal to <code class="docutils literal notranslate"><span class="pre">"first"</span></code> and the second one is
|
||
in turn a sequence of two elements. It will also bind <code class="docutils literal notranslate"><span class="pre">left=subject[1][0]</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">right=subject[1][1]</span></code>, and <code class="docutils literal notranslate"><span class="pre">rest</span> <span class="pre">=</span> <span class="pre">subject[3:]</span></code></p>
|
||
</section>
|
||
<section id="or-patterns">
|
||
<h3><a class="toc-backref" href="#or-patterns" role="doc-backlink">Or patterns</a></h3>
|
||
<p>Going back to the adventure game example, you may find that you’d like to have several
|
||
patterns resulting in the same outcome. For example, you might want the commands
|
||
<code class="docutils literal notranslate"><span class="pre">north</span></code> and <code class="docutils literal notranslate"><span class="pre">go</span> <span class="pre">north</span></code> to be equivalent. You may also desire to have aliases for
|
||
<code class="docutils literal notranslate"><span class="pre">get</span> <span class="pre">X</span></code>, <code class="docutils literal notranslate"><span class="pre">pick</span> <span class="pre">up</span> <span class="pre">X</span></code> and <code class="docutils literal notranslate"><span class="pre">pick</span> <span class="pre">X</span> <span class="pre">up</span></code> for any X.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">|</span></code> symbol in patterns combines them as alternatives. You could for example write:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="o">...</span> <span class="c1"># Other cases</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"north"</span><span class="p">]</span> <span class="o">|</span> <span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="s2">"north"</span><span class="p">]:</span>
|
||
<span class="n">current_room</span> <span class="o">=</span> <span class="n">current_room</span><span class="o">.</span><span class="n">neighbor</span><span class="p">(</span><span class="s2">"north"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"get"</span><span class="p">,</span> <span class="n">obj</span><span class="p">]</span> <span class="o">|</span> <span class="p">[</span><span class="s2">"pick"</span><span class="p">,</span> <span class="s2">"up"</span><span class="p">,</span> <span class="n">obj</span><span class="p">]</span> <span class="o">|</span> <span class="p">[</span><span class="s2">"pick"</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="s2">"up"</span><span class="p">]:</span>
|
||
<span class="o">...</span> <span class="c1"># Code for picking up the given object</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is called an <strong>or pattern</strong> and will produce the expected result. Patterns are
|
||
tried from left to right; this may be relevant to know what is bound if more than
|
||
one alternative matches. An important restriction when writing or patterns is that all
|
||
alternatives should bind the same variables. So a pattern <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">x]</span> <span class="pre">|</span> <span class="pre">[2,</span> <span class="pre">y]</span></code> is not
|
||
allowed because it would make unclear which variable would be bound after a successful
|
||
match. <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">x]</span> <span class="pre">|</span> <span class="pre">[2,</span> <span class="pre">x]</span></code> is perfectly fine and will always bind <code class="docutils literal notranslate"><span class="pre">x</span></code> if successful.</p>
|
||
</section>
|
||
<section id="capturing-matched-sub-patterns">
|
||
<h3><a class="toc-backref" href="#capturing-matched-sub-patterns" role="doc-backlink">Capturing matched sub-patterns</a></h3>
|
||
<p>The first version of our “go” command was written with a <code class="docutils literal notranslate"><span class="pre">["go",</span> <span class="pre">direction]</span></code> pattern.
|
||
The change we did in our last version using the pattern <code class="docutils literal notranslate"><span class="pre">["north"]</span> <span class="pre">|</span> <span class="pre">["go",</span> <span class="pre">"north"]</span></code>
|
||
has some benefits but also some drawbacks in comparison: the latest version allows the
|
||
alias, but also has the direction hardcoded, which will force us to actually have
|
||
separate patterns for north/south/east/west. This leads to some code duplication, but at
|
||
the same time we get better input validation, and we will not be getting into that
|
||
branch if the command entered by the user is <code class="docutils literal notranslate"><span class="pre">"go</span> <span class="pre">figure!"</span></code> instead of a direction.</p>
|
||
<p>We could try to get the best of both worlds doing the following (I’ll omit the aliased
|
||
version without “go” for brevity):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="p">(</span><span class="s2">"north"</span> <span class="o">|</span> <span class="s2">"south"</span> <span class="o">|</span> <span class="s2">"east"</span> <span class="o">|</span> <span class="s2">"west"</span><span class="p">)]:</span>
|
||
<span class="n">current_room</span> <span class="o">=</span> <span class="n">current_room</span><span class="o">.</span><span class="n">neighbor</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
|
||
<span class="c1"># how do I know which direction to go?</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This code is a single branch, and it verifies that the word after “go” is really a
|
||
direction. But the code moving the player around needs to know which one was chosen and
|
||
has no way to do so. What we need is a pattern that behaves like the or pattern but at
|
||
the same time does a capture. We can do so with an <strong>as pattern</strong>:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="p">(</span><span class="s2">"north"</span> <span class="o">|</span> <span class="s2">"south"</span> <span class="o">|</span> <span class="s2">"east"</span> <span class="o">|</span> <span class="s2">"west"</span><span class="p">)</span> <span class="k">as</span> <span class="n">direction</span><span class="p">]:</span>
|
||
<span class="n">current_room</span> <span class="o">=</span> <span class="n">current_room</span><span class="o">.</span><span class="n">neighbor</span><span class="p">(</span><span class="n">direction</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The as-pattern matches whatever pattern is on its left-hand side, but also binds the
|
||
value to a name.</p>
|
||
</section>
|
||
<section id="adding-conditions-to-patterns">
|
||
<h3><a class="toc-backref" href="#adding-conditions-to-patterns" role="doc-backlink">Adding conditions to patterns</a></h3>
|
||
<p>The patterns we have explored above can do some powerful data filtering, but sometimes
|
||
you may wish for the full power of a boolean expression. Let’s say that you would actually
|
||
like to allow a “go” command only in a restricted set of directions based on the possible
|
||
exits from the current_room. We can achieve that by adding a <strong>guard</strong> to our
|
||
case. Guards consist of the <code class="docutils literal notranslate"><span class="pre">if</span></code> keyword followed by any expression:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">command</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="n">direction</span><span class="p">]</span> <span class="k">if</span> <span class="n">direction</span> <span class="ow">in</span> <span class="n">current_room</span><span class="o">.</span><span class="n">exits</span><span class="p">:</span>
|
||
<span class="n">current_room</span> <span class="o">=</span> <span class="n">current_room</span><span class="o">.</span><span class="n">neighbor</span><span class="p">(</span><span class="n">direction</span><span class="p">)</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="p">[</span><span class="s2">"go"</span><span class="p">,</span> <span class="k">_</span><span class="p">]:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Sorry, you can't go that way"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The guard is not part of the pattern, it’s part of the case. It’s only checked if
|
||
the pattern matches, and after all the pattern variables have been bound (that’s why the
|
||
condition can use the <code class="docutils literal notranslate"><span class="pre">direction</span></code> variable in the example above). If the pattern
|
||
matches and the condition is truthy, the body of the case executes normally. If the
|
||
pattern matches but the condition is falsy, the match statement proceeds to check the
|
||
next case as if the pattern hadn’t matched (with the possible side-effect of
|
||
having already bound some variables).</p>
|
||
</section>
|
||
<section id="adding-a-ui-matching-objects">
|
||
<h3><a class="toc-backref" href="#adding-a-ui-matching-objects" role="doc-backlink">Adding a UI: Matching objects</a></h3>
|
||
<p>Your adventure is becoming a success and you have been asked to implement a graphical
|
||
interface. Your UI toolkit of choice allows you to write an event loop where you can get a new
|
||
event object by calling <code class="docutils literal notranslate"><span class="pre">event.get()</span></code>. The resulting object can have different type and
|
||
attributes according to the user action, for example:</p>
|
||
<ul class="simple">
|
||
<li>A <code class="docutils literal notranslate"><span class="pre">KeyPress</span></code> object is generated when the user presses a key. It has a <code class="docutils literal notranslate"><span class="pre">key_name</span></code>
|
||
attribute with the name of the key pressed, and some other attributes regarding modifiers.</li>
|
||
<li>A <code class="docutils literal notranslate"><span class="pre">Click</span></code> object is generated when the user clicks the mouse. It has an attribute
|
||
<code class="docutils literal notranslate"><span class="pre">position</span></code> with the coordinates of the pointer.</li>
|
||
<li>A <code class="docutils literal notranslate"><span class="pre">Quit</span></code> object is generated when the user clicks on the close button for the game
|
||
window.</li>
|
||
</ul>
|
||
<p>Rather than writing multiple <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> checks, you can use patterns to recognize
|
||
different kinds of objects, and also apply patterns to its attributes:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="n">Click</span><span class="p">(</span><span class="n">position</span><span class="o">=</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)):</span>
|
||
<span class="n">handle_click_at</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">KeyPress</span><span class="p">(</span><span class="n">key_name</span><span class="o">=</span><span class="s2">"Q"</span><span class="p">)</span> <span class="o">|</span> <span class="n">Quit</span><span class="p">():</span>
|
||
<span class="n">game</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
|
||
<span class="k">case</span> <span class="n">KeyPress</span><span class="p">(</span><span class="n">key_name</span><span class="o">=</span><span class="s2">"up arrow"</span><span class="p">):</span>
|
||
<span class="n">game</span><span class="o">.</span><span class="n">go_north</span><span class="p">()</span>
|
||
<span class="o">...</span>
|
||
<span class="k">case</span> <span class="n">KeyPress</span><span class="p">():</span>
|
||
<span class="k">pass</span> <span class="c1"># Ignore other keystrokes</span>
|
||
<span class="k">case</span> <span class="n">other_event</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unrecognized event: </span><span class="si">{</span><span class="n">other_event</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A pattern like <code class="docutils literal notranslate"><span class="pre">Click(position=(x,</span> <span class="pre">y))</span></code> only matches if the type of the event is
|
||
a subclass of the <code class="docutils literal notranslate"><span class="pre">Click</span></code> class. It will also require that the event has a <code class="docutils literal notranslate"><span class="pre">position</span></code>
|
||
attribute that matches the <code class="docutils literal notranslate"><span class="pre">(x,</span> <span class="pre">y)</span></code> pattern. If there’s a match, the locals <code class="docutils literal notranslate"><span class="pre">x</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">y</span></code> will get the expected values.</p>
|
||
<p>A pattern like <code class="docutils literal notranslate"><span class="pre">KeyPress()</span></code>, with no arguments will match any object which is an
|
||
instance of the <code class="docutils literal notranslate"><span class="pre">KeyPress</span></code> class. Only the attributes you specify in the pattern are
|
||
matched, and any other attributes are ignored.</p>
|
||
</section>
|
||
<section id="matching-positional-attributes">
|
||
<h3><a class="toc-backref" href="#matching-positional-attributes" role="doc-backlink">Matching positional attributes</a></h3>
|
||
<p>The previous section described how to match named attributes when doing an object match.
|
||
For some objects it could be convenient to describe the matched arguments by position
|
||
(especially if there are only a few attributes and they have a “standard” ordering).
|
||
If the classes that you are using are named tuples or dataclasses, you can do that by
|
||
following the same order that you’d use when constructing an object. For example, if
|
||
the UI framework above defines their class like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
|
||
|
||
<span class="nd">@dataclass</span>
|
||
<span class="k">class</span> <span class="nc">Click</span><span class="p">:</span>
|
||
<span class="n">position</span><span class="p">:</span> <span class="nb">tuple</span>
|
||
<span class="n">button</span><span class="p">:</span> <span class="n">Button</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>then you can rewrite your match statement above as:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="n">Click</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)):</span>
|
||
<span class="n">handle_click_at</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">(x,</span> <span class="pre">y)</span></code> pattern will be automatically matched against the <code class="docutils literal notranslate"><span class="pre">position</span></code>
|
||
attribute, because the first argument in the pattern corresponds to the first
|
||
attribute in your dataclass definition.</p>
|
||
<p>Other classes don’t have a natural ordering of their attributes so you’re required to
|
||
use explicit names in your pattern to match with their attributes. However, it’s possible
|
||
to manually specify the ordering of the attributes allowing positional matching, like in
|
||
this alternative definition:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Click</span><span class="p">:</span>
|
||
<span class="n">__match_args__</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"position"</span><span class="p">,</span> <span class="s2">"button"</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">pos</span><span class="p">,</span> <span class="n">btn</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">position</span> <span class="o">=</span> <span class="n">pos</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">button</span> <span class="o">=</span> <span class="n">btn</span>
|
||
<span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">__match_args__</span></code> special attribute defines an explicit order for your attributes
|
||
that can be used in patterns like <code class="docutils literal notranslate"><span class="pre">case</span> <span class="pre">Click((x,y))</span></code>.</p>
|
||
</section>
|
||
<section id="matching-against-constants-and-enums">
|
||
<h3><a class="toc-backref" href="#matching-against-constants-and-enums" role="doc-backlink">Matching against constants and enums</a></h3>
|
||
<p>Your pattern above treats all mouse buttons the same, and you have decided that you
|
||
want to accept left-clicks, and ignore other buttons. While doing so, you notice that
|
||
the <code class="docutils literal notranslate"><span class="pre">button</span></code> attribute is typed as a <code class="docutils literal notranslate"><span class="pre">Button</span></code> which is an enumeration built with
|
||
<code class="docutils literal notranslate"><span class="pre">enum.Enum</span></code>. You can in fact match against enumeration values like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
|
||
<span class="k">case</span> <span class="n">Click</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="n">button</span><span class="o">=</span><span class="n">Button</span><span class="o">.</span><span class="n">LEFT</span><span class="p">):</span> <span class="c1"># This is a left click</span>
|
||
<span class="n">handle_click_at</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Click</span><span class="p">():</span>
|
||
<span class="k">pass</span> <span class="c1"># ignore other clicks</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This will work with any dotted name (like <code class="docutils literal notranslate"><span class="pre">math.pi</span></code>). However an unqualified name (i.e.
|
||
a bare name with no dots) will be always interpreted as a capture pattern, so avoid
|
||
that ambiguity by always using qualified constants in patterns.</p>
|
||
</section>
|
||
<section id="going-to-the-cloud-mappings">
|
||
<h3><a class="toc-backref" href="#going-to-the-cloud-mappings" role="doc-backlink">Going to the cloud: Mappings</a></h3>
|
||
<p>You have decided to make an online version of your game. All
|
||
of your logic will be in a server, and the UI in a client which will communicate using
|
||
JSON messages. Via the <code class="docutils literal notranslate"><span class="pre">json</span></code> module, those will be mapped to Python dictionaries,
|
||
lists and other builtin objects.</p>
|
||
<p>Our client will receive a list of dictionaries (parsed from JSON) of actions to take,
|
||
each element looking for example like these:</p>
|
||
<ul class="simple">
|
||
<li><code class="docutils literal notranslate"><span class="pre">{"text":</span> <span class="pre">"The</span> <span class="pre">shop</span> <span class="pre">keeper</span> <span class="pre">says</span> <span class="pre">'Ah!</span> <span class="pre">We</span> <span class="pre">have</span> <span class="pre">Camembert,</span> <span class="pre">yes</span> <span class="pre">sir'",</span> <span class="pre">"color":</span> <span class="pre">"blue"}</span></code></li>
|
||
<li>If the client should make a pause <code class="docutils literal notranslate"><span class="pre">{"sleep":</span> <span class="pre">3}</span></code></li>
|
||
<li>To play a sound <code class="docutils literal notranslate"><span class="pre">{"sound":</span> <span class="pre">"filename.ogg",</span> <span class="pre">"format":</span> <span class="pre">"ogg"}</span></code></li>
|
||
</ul>
|
||
<p>Until now, our patterns have processed sequences, but there are patterns to match
|
||
mappings based on their present keys. In this case you could use:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">action</span> <span class="ow">in</span> <span class="n">actions</span><span class="p">:</span>
|
||
<span class="k">match</span> <span class="n">action</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="p">{</span><span class="s2">"text"</span><span class="p">:</span> <span class="n">message</span><span class="p">,</span> <span class="s2">"color"</span><span class="p">:</span> <span class="n">c</span><span class="p">}:</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">set_text_color</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">display</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">{</span><span class="s2">"sleep"</span><span class="p">:</span> <span class="n">duration</span><span class="p">}:</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">duration</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">{</span><span class="s2">"sound"</span><span class="p">:</span> <span class="n">url</span><span class="p">,</span> <span class="s2">"format"</span><span class="p">:</span> <span class="s2">"ogg"</span><span class="p">}:</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="p">{</span><span class="s2">"sound"</span><span class="p">:</span> <span class="k">_</span><span class="p">,</span> <span class="s2">"format"</span><span class="p">:</span> <span class="n">_</span><span class="p">}:</span>
|
||
<span class="n">warning</span><span class="p">(</span><span class="s2">"Unsupported audio format"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The keys in your mapping pattern need to be literals, but the values can be any
|
||
pattern. As in sequence patterns, all subpatterns have to match for the general
|
||
pattern to match.</p>
|
||
<p>You can use <code class="docutils literal notranslate"><span class="pre">**rest</span></code> within a mapping pattern to capture additional keys in
|
||
the subject. Note that if you omit this, extra keys in the subject will be
|
||
ignored while matching, i.e. the message
|
||
<code class="docutils literal notranslate"><span class="pre">{"text":</span> <span class="pre">"foo",</span> <span class="pre">"color":</span> <span class="pre">"red",</span> <span class="pre">"style":</span> <span class="pre">"bold"}</span></code> will match the first pattern
|
||
in the example above.</p>
|
||
</section>
|
||
<section id="matching-builtin-classes">
|
||
<h3><a class="toc-backref" href="#matching-builtin-classes" role="doc-backlink">Matching builtin classes</a></h3>
|
||
<p>The code above could use some validation. Given that messages came from an external
|
||
source, the types of the field could be wrong, leading to bugs or security issues.</p>
|
||
<p>Any class is a valid match target, and that includes built-in classes like <code class="docutils literal notranslate"><span class="pre">bool</span></code>
|
||
<code class="docutils literal notranslate"><span class="pre">str</span></code> or <code class="docutils literal notranslate"><span class="pre">int</span></code>. That allows us to combine the code above with a class pattern.
|
||
So instead of writing <code class="docutils literal notranslate"><span class="pre">{"text":</span> <span class="pre">message,</span> <span class="pre">"color":</span> <span class="pre">c}</span></code> we can use
|
||
<code class="docutils literal notranslate"><span class="pre">{"text":</span> <span class="pre">str()</span> <span class="pre">as</span> <span class="pre">message,</span> <span class="pre">"color":</span> <span class="pre">str()</span> <span class="pre">as</span> <span class="pre">c}</span></code> to ensure that <code class="docutils literal notranslate"><span class="pre">message</span></code> and <code class="docutils literal notranslate"><span class="pre">c</span></code>
|
||
are both strings. For many builtin classes (see <a class="pep reference internal" href="../pep-0634/" title="PEP 634 – Structural Pattern Matching: Specification">PEP 634</a> for the whole list), you can
|
||
use a positional parameter as a shorthand, writing <code class="docutils literal notranslate"><span class="pre">str(c)</span></code> rather than <code class="docutils literal notranslate"><span class="pre">str()</span> <span class="pre">as</span> <span class="pre">c</span></code>.
|
||
The fully rewritten version looks like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">action</span> <span class="ow">in</span> <span class="n">actions</span><span class="p">:</span>
|
||
<span class="k">match</span> <span class="n">action</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="p">{</span><span class="s2">"text"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">message</span><span class="p">),</span> <span class="s2">"color"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">c</span><span class="p">)}:</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">set_text_color</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">display</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">{</span><span class="s2">"sleep"</span><span class="p">:</span> <span class="nb">float</span><span class="p">(</span><span class="n">duration</span><span class="p">)}:</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">duration</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">{</span><span class="s2">"sound"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">url</span><span class="p">),</span> <span class="s2">"format"</span><span class="p">:</span> <span class="s2">"ogg"</span><span class="p">}:</span>
|
||
<span class="n">ui</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="p">{</span><span class="s2">"sound"</span><span class="p">:</span> <span class="k">_</span><span class="p">,</span> <span class="s2">"format"</span><span class="p">:</span> <span class="n">_</span><span class="p">}:</span>
|
||
<span class="n">warning</span><span class="p">(</span><span class="s2">"Unsupported audio format"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="appendix-a-quick-intro">
|
||
<span id="pep-636-appendix-a"></span><h2><a class="toc-backref" href="#appendix-a-quick-intro" role="doc-backlink">Appendix A – Quick Intro</a></h2>
|
||
<p>A match statement takes an expression and compares its value to successive
|
||
patterns given as one or more case blocks. This is superficially
|
||
similar to a switch statement in C, Java or JavaScript (and many
|
||
other languages), but much more powerful.</p>
|
||
<p>The simplest form compares a subject value against one or more literals:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">http_error</span><span class="p">(</span><span class="n">status</span><span class="p">):</span>
|
||
<span class="k">match</span> <span class="n">status</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="mi">400</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"Bad request"</span>
|
||
<span class="k">case</span> <span class="mi">404</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"Not found"</span>
|
||
<span class="k">case</span> <span class="mi">418</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"I'm a teapot"</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"Something's wrong with the Internet"</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note the last block: the “variable name” <code class="docutils literal notranslate"><span class="pre">_</span></code> acts as a <em>wildcard</em> and
|
||
never fails to match.</p>
|
||
<p>You can combine several literals in a single pattern using <code class="docutils literal notranslate"><span class="pre">|</span></code> (“or”):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">case</span> <span class="mi">401</span> <span class="o">|</span> <span class="mi">403</span> <span class="o">|</span> <span class="mi">404</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="s2">"Not allowed"</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Patterns can look like unpacking assignments, and can be used to bind
|
||
variables:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># point is an (x, y) tuple</span>
|
||
<span class="k">match</span> <span class="n">point</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Origin"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Y=</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"X=</span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"X=</span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">, Y=</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Not a point"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Study that one carefully! The first pattern has two literals, and can
|
||
be thought of as an extension of the literal pattern shown above. But
|
||
the next two patterns combine a literal and a variable, and the
|
||
variable <em>binds</em> a value from the subject (<code class="docutils literal notranslate"><span class="pre">point</span></code>). The fourth
|
||
pattern captures two values, which makes it conceptually similar to
|
||
the unpacking assignment <code class="docutils literal notranslate"><span class="pre">(x,</span> <span class="pre">y)</span> <span class="pre">=</span> <span class="pre">point</span></code>.</p>
|
||
<p>If you are using classes to structure your data
|
||
you can use the class name followed by an argument list resembling a
|
||
constructor, but with the ability to capture attributes into variables:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
|
||
|
||
<span class="nd">@dataclass</span>
|
||
<span class="k">class</span> <span class="nc">Point</span><span class="p">:</span>
|
||
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
||
<span class="n">y</span><span class="p">:</span> <span class="nb">int</span>
|
||
|
||
<span class="k">def</span> <span class="nf">where_is</span><span class="p">(</span><span class="n">point</span><span class="p">):</span>
|
||
<span class="k">match</span> <span class="n">point</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Origin"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Y=</span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"X=</span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Point</span><span class="p">():</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Somewhere else"</span><span class="p">)</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Not a point"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>You can use positional parameters with some builtin classes that provide an
|
||
ordering for their attributes (e.g. dataclasses). You can also define a specific
|
||
position for attributes in patterns by setting the <code class="docutils literal notranslate"><span class="pre">__match_args__</span></code> special
|
||
attribute in your classes. If it’s set to (“x”, “y”), the following patterns are all
|
||
equivalent (and all bind the <code class="docutils literal notranslate"><span class="pre">y</span></code> attribute to the <code class="docutils literal notranslate"><span class="pre">var</span></code> variable):</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Point</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">var</span><span class="p">)</span>
|
||
<span class="n">Point</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">var</span><span class="p">)</span>
|
||
<span class="n">Point</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="n">var</span><span class="p">)</span>
|
||
<span class="n">Point</span><span class="p">(</span><span class="n">y</span><span class="o">=</span><span class="n">var</span><span class="p">,</span> <span class="n">x</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Patterns can be arbitrarily nested. For example, if we have a short
|
||
list of points, we could match it like this:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">points</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="p">[]:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"No points"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="n">Point</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"The origin"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Single point </span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">, </span><span class="si">{</span><span class="n">y</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="p">[</span><span class="n">Point</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">y1</span><span class="p">),</span> <span class="n">Point</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">y2</span><span class="p">)]:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Two on the Y axis at </span><span class="si">{</span><span class="n">y1</span><span class="si">}</span><span class="s2">, </span><span class="si">{</span><span class="n">y2</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Something else"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We can add an <code class="docutils literal notranslate"><span class="pre">if</span></code> clause to a pattern, known as a “guard”. If the
|
||
guard is false, <code class="docutils literal notranslate"><span class="pre">match</span></code> goes on to try the next case block. Note
|
||
that value capture happens before the guard is evaluated:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">match</span> <span class="n">point</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="n">y</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Y=X at </span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Not on the diagonal"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Several other key features:</p>
|
||
<ul>
|
||
<li>Like unpacking assignments, tuple and list patterns have exactly the
|
||
same meaning and actually match arbitrary sequences. An important
|
||
exception is that they don’t match iterators or strings.
|
||
(Technically, the subject must be an instance of
|
||
<code class="docutils literal notranslate"><span class="pre">collections.abc.Sequence</span></code>.)</li>
|
||
<li>Sequence patterns support wildcards: <code class="docutils literal notranslate"><span class="pre">[x,</span> <span class="pre">y,</span> <span class="pre">*rest]</span></code> and <code class="docutils literal notranslate"><span class="pre">(x,</span> <span class="pre">y,</span>
|
||
<span class="pre">*rest)</span></code> work similar to wildcards in unpacking assignments. The
|
||
name after <code class="docutils literal notranslate"><span class="pre">*</span></code> may also be <code class="docutils literal notranslate"><span class="pre">_</span></code>, so <code class="docutils literal notranslate"><span class="pre">(x,</span> <span class="pre">y,</span> <span class="pre">*_)</span></code> matches a sequence
|
||
of at least two items without binding the remaining items.</li>
|
||
<li>Mapping patterns: <code class="docutils literal notranslate"><span class="pre">{"bandwidth":</span> <span class="pre">b,</span> <span class="pre">"latency":</span> <span class="pre">l}</span></code> captures the
|
||
<code class="docutils literal notranslate"><span class="pre">"bandwidth"</span></code> and <code class="docutils literal notranslate"><span class="pre">"latency"</span></code> values from a dict. Unlike sequence
|
||
patterns, extra keys are ignored. A wildcard <code class="docutils literal notranslate"><span class="pre">**rest</span></code> is also
|
||
supported. (But <code class="docutils literal notranslate"><span class="pre">**_</span></code> would be redundant, so it is not allowed.)</li>
|
||
<li>Subpatterns may be captured using the <code class="docutils literal notranslate"><span class="pre">as</span></code> keyword:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">case</span> <span class="p">(</span><span class="n">Point</span><span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">y1</span><span class="p">),</span> <span class="n">Point</span><span class="p">(</span><span class="n">x2</span><span class="p">,</span> <span class="n">y2</span><span class="p">)</span> <span class="k">as</span> <span class="n">p2</span><span class="p">):</span> <span class="o">...</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
<li>Most literals are compared by equality, however the singletons <code class="docutils literal notranslate"><span class="pre">True</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">False</span></code> and <code class="docutils literal notranslate"><span class="pre">None</span></code> are compared by identity.</li>
|
||
<li>Patterns may use named constants. These must be dotted names
|
||
to prevent them from being interpreted as capture variable:<div class="highlight-default notranslate"><div class="highlight"><pre><span></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">Color</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||
<span class="n">RED</span> <span class="o">=</span> <span class="mi">0</span>
|
||
<span class="n">GREEN</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="n">BLUE</span> <span class="o">=</span> <span class="mi">2</span>
|
||
|
||
<span class="k">match</span> <span class="n">color</span><span class="p">:</span>
|
||
<span class="k">case</span> <span class="n">Color</span><span class="o">.</span><span class="n">RED</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"I see red!"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Color</span><span class="o">.</span><span class="n">GREEN</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Grass is green"</span><span class="p">)</span>
|
||
<span class="k">case</span> <span class="n">Color</span><span class="o">.</span><span class="n">BLUE</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"I'm feeling the blues :("</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</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-0636.rst">https://github.com/python/peps/blob/main/peps/pep-0636.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0636.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="#tutorial">Tutorial</a><ul>
|
||
<li><a class="reference internal" href="#matching-sequences">Matching sequences</a></li>
|
||
<li><a class="reference internal" href="#matching-multiple-patterns">Matching multiple patterns</a></li>
|
||
<li><a class="reference internal" href="#matching-specific-values">Matching specific values</a></li>
|
||
<li><a class="reference internal" href="#matching-multiple-values">Matching multiple values</a></li>
|
||
<li><a class="reference internal" href="#adding-a-wildcard">Adding a wildcard</a></li>
|
||
<li><a class="reference internal" href="#composing-patterns">Composing patterns</a></li>
|
||
<li><a class="reference internal" href="#or-patterns">Or patterns</a></li>
|
||
<li><a class="reference internal" href="#capturing-matched-sub-patterns">Capturing matched sub-patterns</a></li>
|
||
<li><a class="reference internal" href="#adding-conditions-to-patterns">Adding conditions to patterns</a></li>
|
||
<li><a class="reference internal" href="#adding-a-ui-matching-objects">Adding a UI: Matching objects</a></li>
|
||
<li><a class="reference internal" href="#matching-positional-attributes">Matching positional attributes</a></li>
|
||
<li><a class="reference internal" href="#matching-against-constants-and-enums">Matching against constants and enums</a></li>
|
||
<li><a class="reference internal" href="#going-to-the-cloud-mappings">Going to the cloud: Mappings</a></li>
|
||
<li><a class="reference internal" href="#matching-builtin-classes">Matching builtin classes</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#appendix-a-quick-intro">Appendix A – Quick Intro</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-0636.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> |