python-peps/pep-0634/index.html

756 lines
52 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 634 Structural Pattern Matching: Specification | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0634/">
<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 634 Structural Pattern Matching: Specification | peps.python.org'>
<meta property="og:description" content="This PEP provides the technical specification for the match statement. It replaces PEP 622, which is hereby split in three parts:">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0634/">
<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 provides the technical specification for the match statement. It replaces PEP 622, which is hereby split in three parts:">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 634</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 634 Structural Pattern Matching: Specification</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Brandt Bucher &lt;brandt&#32;&#97;t&#32;python.org&gt;,
Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/">Python-Dev list</a></dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">12-Sep-2020</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">3.10</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">22-Oct-2020, 08-Feb-2021</dd>
<dt class="field-odd">Replaces<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="../pep-0622/">622</a></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&#64;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="#syntax-and-semantics">Syntax and Semantics</a><ul>
<li><a class="reference internal" href="#overview-and-terminology">Overview and Terminology</a></li>
<li><a class="reference internal" href="#the-match-statement">The Match Statement</a><ul>
<li><a class="reference internal" href="#match-semantics">Match Semantics</a></li>
<li><a class="reference internal" href="#guards">Guards</a></li>
<li><a class="reference internal" href="#irrefutable-case-blocks">Irrefutable case blocks</a></li>
</ul>
</li>
<li><a class="reference internal" href="#patterns">Patterns</a><ul>
<li><a class="reference internal" href="#as-patterns">AS Patterns</a></li>
<li><a class="reference internal" href="#or-patterns">OR Patterns</a></li>
<li><a class="reference internal" href="#literal-patterns">Literal Patterns</a></li>
<li><a class="reference internal" href="#capture-patterns">Capture Patterns</a></li>
<li><a class="reference internal" href="#wildcard-pattern">Wildcard Pattern</a></li>
<li><a class="reference internal" href="#value-patterns">Value Patterns</a></li>
<li><a class="reference internal" href="#group-patterns">Group Patterns</a></li>
<li><a class="reference internal" href="#sequence-patterns">Sequence Patterns</a></li>
<li><a class="reference internal" href="#mapping-patterns">Mapping Patterns</a></li>
<li><a class="reference internal" href="#class-patterns">Class Patterns</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#side-effects-and-undefined-behavior">Side Effects and Undefined Behavior</a></li>
<li><a class="reference internal" href="#the-standard-library">The Standard Library</a></li>
<li><a class="reference internal" href="#appendix-a-full-grammar">Appendix A Full Grammar</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<div class="pep-banner canonical-doc sticky-banner admonition important">
<p class="admonition-title">Important</p>
<p>This PEP is a historical document. The up-to-date, canonical documentation can now be found at <a class="reference external" href="https://docs.python.org/3/reference/compound_stmts.html#match" title="(in Python v3.13)"><span>The match statement</span></a>.</p>
<p class="close-button">×</p>
<p>See <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a> for how to propose changes.</p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP provides the technical specification for the match
statement. It replaces <a class="pep reference internal" href="../pep-0622/" title="PEP 622 Structural Pattern Matching">PEP 622</a>, which is hereby split in three parts:</p>
<ul class="simple">
<li><a class="pep reference internal" href="../pep-0634/" title="PEP 634 Structural Pattern Matching: Specification">PEP 634</a>: Specification</li>
<li><a class="pep reference internal" href="../pep-0635/" title="PEP 635 Structural Pattern Matching: Motivation and Rationale">PEP 635</a>: Motivation and Rationale</li>
<li><a class="pep reference internal" href="../pep-0636/" title="PEP 636 Structural Pattern Matching: Tutorial">PEP 636</a>: Tutorial</li>
</ul>
<p>This PEP is intentionally devoid of commentary; the motivation and all
explanations of our design choices are in <a class="pep reference internal" href="../pep-0635/" title="PEP 635 Structural Pattern Matching: Motivation and Rationale">PEP 635</a>. First-time readers
are encouraged to start with <a class="pep reference internal" href="../pep-0636/" title="PEP 636 Structural Pattern Matching: Tutorial">PEP 636</a>, which provides a gentler
introduction to the concepts, syntax and semantics of patterns.</p>
</section>
<section id="syntax-and-semantics">
<h2><a class="toc-backref" href="#syntax-and-semantics" role="doc-backlink">Syntax and Semantics</a></h2>
<p>See <a class="reference internal" href="#appendix-a">Appendix A</a> for the complete grammar.</p>
<section id="overview-and-terminology">
<h3><a class="toc-backref" href="#overview-and-terminology" role="doc-backlink">Overview and Terminology</a></h3>
<p>The pattern matching process takes as input a pattern (following
<code class="docutils literal notranslate"><span class="pre">case</span></code>) and a subject value (following <code class="docutils literal notranslate"><span class="pre">match</span></code>). Phrases to
describe the process include “the pattern is matched with (or against)
the subject value” and “we match the pattern against (or with) the
subject value”.</p>
<p>The primary outcome of pattern matching is success or failure. In
case of success we may say “the pattern succeeds”, “the match
succeeds”, or “the pattern matches the subject value”.</p>
<p>In many cases a pattern contains subpatterns, and success or failure
is determined by the success or failure of matching those subpatterns
against the value (e.g., for OR patterns) or against parts of the
value (e.g., for sequence patterns). This process typically processes
the subpatterns from left to right until the overall outcome is
determined. E.g., an OR pattern succeeds at the first succeeding
subpattern, while a sequence patterns fails at the first failing
subpattern.</p>
<p>A secondary outcome of pattern matching may be one or more name
bindings. We may say “the pattern binds a value to a name”. When
subpatterns tried until the first success, only the bindings due to
the successful subpattern are valid; when trying until the first
failure, the bindings are merged. Several more rules, explained
below, apply to these cases.</p>
</section>
<section id="the-match-statement">
<h3><a class="toc-backref" href="#the-match-statement" role="doc-backlink">The Match Statement</a></h3>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>match_stmt: &quot;match&quot; subject_expr &#39;:&#39; NEWLINE INDENT case_block+ DEDENT
subject_expr:
| star_named_expression &#39;,&#39; star_named_expressions?
| named_expression
case_block: &quot;case&quot; patterns [guard] &#39;:&#39; block
guard: &#39;if&#39; named_expression
</pre></div>
</div>
<p>The rules <code class="docutils literal notranslate"><span class="pre">star_named_expression</span></code>, <code class="docutils literal notranslate"><span class="pre">star_named_expressions</span></code>,
<code class="docutils literal notranslate"><span class="pre">named_expression</span></code> and <code class="docutils literal notranslate"><span class="pre">block</span></code> are part of the <a class="reference external" href="https://docs.python.org/3.10/reference/grammar.html">standard Python
grammar</a>.</p>
<p>The rule <code class="docutils literal notranslate"><span class="pre">patterns</span></code> is specified below.</p>
<p>For context, <code class="docutils literal notranslate"><span class="pre">match_stmt</span></code> is a new alternative for
<code class="docutils literal notranslate"><span class="pre">compound_statement</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">compound_statement</span><span class="p">:</span>
<span class="o">|</span> <span class="n">if_stmt</span>
<span class="o">...</span>
<span class="o">|</span> <span class="n">match_stmt</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">match</span></code> and <code class="docutils literal notranslate"><span class="pre">case</span></code> keywords are soft keywords, i.e. they are
not reserved words in other grammatical contexts (including at the
start of a line if there is no colon where expected). This implies
that they are recognized as keywords when part of a match
statement or case block only, and are allowed to be used in all
other contexts as variable or argument names.</p>
<section id="match-semantics">
<h4><a class="toc-backref" href="#match-semantics" role="doc-backlink">Match Semantics</a></h4>
<p>The match statement first evaluates the subject expression. If a
comma is present a tuple is constructed using the standard rules.</p>
<p>The resulting subject value is then used to select the first case
block whose patterns succeeds matching it <em>and</em> whose guard condition
(if present) is “truthy”. If no case blocks qualify the match
statement is complete; otherwise, the block of the selected case block
is executed. The usual rules for executing a block nested inside a
compound statement apply (e.g. an <code class="docutils literal notranslate"><span class="pre">if</span></code> statement).</p>
<p>Name bindings made during a successful pattern match outlive the
executed block and can be used after the match statement.</p>
<p>During failed pattern matches, some subpatterns may succeed. For
example, while matching the pattern <code class="docutils literal notranslate"><span class="pre">(0,</span> <span class="pre">x,</span> <span class="pre">1)</span></code> with the value <code class="docutils literal notranslate"><span class="pre">[0,</span>
<span class="pre">1,</span> <span class="pre">2]</span></code>, the subpattern <code class="docutils literal notranslate"><span class="pre">x</span></code> may succeed if the list elements are
matched from left to right. The implementation may choose to either
make persistent bindings for those partial matches or not. User code
including a match statement should not rely on the bindings being
made for a failed match, but also shouldnt assume that variables are
unchanged by a failed match. This part of the behavior is left
intentionally unspecified so different implementations can add
optimizations, and to prevent introducing semantic restrictions that
could limit the extensibility of this feature.</p>
<p>The precise pattern binding rules vary per pattern type and are
specified below.</p>
</section>
<section id="guards">
<span id="id1"></span><h4><a class="toc-backref" href="#guards" role="doc-backlink">Guards</a></h4>
<p>If a guard is present on a case block, once the pattern or patterns in
the case block succeed, the expression in the guard is evaluated. If
this raises an exception, the exception bubbles up. Otherwise, if the
condition is “truthy” the case block is selected; if it is “falsy” the
case block is not selected.</p>
<p>Since guards are expressions they are allowed to have side effects.
Guard evaluation must proceed from the first to the last case block,
one at a time, skipping case blocks whose pattern(s) dont all
succeed. (I.e., even if determining whether those patterns succeed
may happen out of order, guard evaluation must happen in order.)
Guard evaluation must stop once a case block is selected.</p>
</section>
<section id="irrefutable-case-blocks">
<h4><a class="toc-backref" href="#irrefutable-case-blocks" role="doc-backlink">Irrefutable case blocks</a></h4>
<p>A pattern is considered irrefutable if we can prove from its syntax
alone that it will always succeed. In particular, capture patterns
and wildcard patterns are irrefutable, and so are AS patterns whose
left-hand side is irrefutable, OR patterns containing at least
one irrefutable pattern, and parenthesized irrefutable patterns.</p>
<p>A case block is considered irrefutable if it has no guard and its
pattern is irrefutable.</p>
<p>A match statement may have at most one irrefutable case block, and it
must be last.</p>
</section>
</section>
<section id="patterns">
<span id="id2"></span><h3><a class="toc-backref" href="#patterns" role="doc-backlink">Patterns</a></h3>
<p>The top-level syntax for patterns is as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">patterns</span><span class="p">:</span> <span class="n">open_sequence_pattern</span> <span class="o">|</span> <span class="n">pattern</span>
<span class="n">pattern</span><span class="p">:</span> <span class="n">as_pattern</span> <span class="o">|</span> <span class="n">or_pattern</span>
<span class="n">as_pattern</span><span class="p">:</span> <span class="n">or_pattern</span> <span class="s1">&#39;as&#39;</span> <span class="n">capture_pattern</span>
<span class="n">or_pattern</span><span class="p">:</span> <span class="s1">&#39;|&#39;</span><span class="o">.</span><span class="n">closed_pattern</span><span class="o">+</span>
<span class="n">closed_pattern</span><span class="p">:</span>
<span class="o">|</span> <span class="n">literal_pattern</span>
<span class="o">|</span> <span class="n">capture_pattern</span>
<span class="o">|</span> <span class="n">wildcard_pattern</span>
<span class="o">|</span> <span class="n">value_pattern</span>
<span class="o">|</span> <span class="n">group_pattern</span>
<span class="o">|</span> <span class="n">sequence_pattern</span>
<span class="o">|</span> <span class="n">mapping_pattern</span>
<span class="o">|</span> <span class="n">class_pattern</span>
</pre></div>
</div>
<section id="as-patterns">
<h4><a class="toc-backref" href="#as-patterns" role="doc-backlink">AS Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">as_pattern</span><span class="p">:</span> <span class="n">or_pattern</span> <span class="s1">&#39;as&#39;</span> <span class="n">capture_pattern</span>
</pre></div>
</div>
<p>(Note: the name on the right may not be <code class="docutils literal notranslate"><span class="pre">_</span></code>.)</p>
<p>An AS pattern matches the OR pattern on the left of the <code class="docutils literal notranslate"><span class="pre">as</span></code>
keyword against the subject. If this fails, the AS pattern fails.
Otherwise, the AS pattern binds the subject to the name on the right
of the <code class="docutils literal notranslate"><span class="pre">as</span></code> keyword and succeeds.</p>
</section>
<section id="or-patterns">
<h4><a class="toc-backref" href="#or-patterns" role="doc-backlink">OR Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">or_pattern</span><span class="p">:</span> <span class="s1">&#39;|&#39;</span><span class="o">.</span><span class="n">closed_pattern</span><span class="o">+</span>
</pre></div>
</div>
<p>When two or more patterns are separated by vertical bars (<code class="docutils literal notranslate"><span class="pre">|</span></code>),
this is called an OR pattern. (A single closed pattern is just that.)</p>
<p>Only the final subpattern may be irrefutable.</p>
<p>Each subpattern must bind the same set of names.</p>
<p>An OR pattern matches each of its subpatterns in turn to the subject,
until one succeeds. The OR pattern is then deemed to succeed.
If none of the subpatterns succeed the OR pattern fails.</p>
</section>
<section id="literal-patterns">
<span id="literal-pattern"></span><h4><a class="toc-backref" href="#literal-patterns" role="doc-backlink">Literal Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">literal_pattern</span><span class="p">:</span>
<span class="o">|</span> <span class="n">signed_number</span>
<span class="o">|</span> <span class="n">signed_number</span> <span class="s1">&#39;+&#39;</span> <span class="n">NUMBER</span>
<span class="o">|</span> <span class="n">signed_number</span> <span class="s1">&#39;-&#39;</span> <span class="n">NUMBER</span>
<span class="o">|</span> <span class="n">strings</span>
<span class="o">|</span> <span class="s1">&#39;None&#39;</span>
<span class="o">|</span> <span class="s1">&#39;True&#39;</span>
<span class="o">|</span> <span class="s1">&#39;False&#39;</span>
<span class="n">signed_number</span><span class="p">:</span> <span class="n">NUMBER</span> <span class="o">|</span> <span class="s1">&#39;-&#39;</span> <span class="n">NUMBER</span>
</pre></div>
</div>
<p>The rule <code class="docutils literal notranslate"><span class="pre">strings</span></code> and the token <code class="docutils literal notranslate"><span class="pre">NUMBER</span></code> are defined in the
standard Python grammar.</p>
<p>Triple-quoted strings are supported. Raw strings and byte strings
are supported. F-strings are not supported.</p>
<p>The forms <code class="docutils literal notranslate"><span class="pre">signed_number</span> <span class="pre">'+'</span> <span class="pre">NUMBER</span></code> and <code class="docutils literal notranslate"><span class="pre">signed_number</span> <span class="pre">'-'</span>
<span class="pre">NUMBER</span></code> are only permitted to express complex numbers; they require a
real number on the left and an imaginary number on the right.</p>
<p>A literal pattern succeeds if the subject value compares equal to the
value expressed by the literal, using the following comparisons rules:</p>
<ul class="simple">
<li>Numbers and strings are compared using the <code class="docutils literal notranslate"><span class="pre">==</span></code> operator.</li>
<li>The singleton literals <code class="docutils literal notranslate"><span class="pre">None</span></code>, <code class="docutils literal notranslate"><span class="pre">True</span></code> and <code class="docutils literal notranslate"><span class="pre">False</span></code> are compared
using the <code class="docutils literal notranslate"><span class="pre">is</span></code> operator.</li>
</ul>
</section>
<section id="capture-patterns">
<span id="capture-pattern"></span><h4><a class="toc-backref" href="#capture-patterns" role="doc-backlink">Capture Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>capture_pattern: !&quot;_&quot; NAME
</pre></div>
</div>
<p>The single underscore (<code class="docutils literal notranslate"><span class="pre">_</span></code>) is not a capture pattern (this is what
<code class="docutils literal notranslate"><span class="pre">!&quot;_&quot;</span></code> expresses). It is treated as a <a class="reference internal" href="#id3">wildcard pattern</a>.</p>
<p>A capture pattern always succeeds. It binds the subject value to the
name using the scoping rules for name binding established for the
walrus operator in <a class="pep reference internal" href="../pep-0572/" title="PEP 572 Assignment Expressions">PEP 572</a>. (Summary: the name becomes a local
variable in the closest containing function scope unless theres an
applicable <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> or <code class="docutils literal notranslate"><span class="pre">global</span></code> statement.)</p>
<p>In a given pattern, a given name may be bound only once. This
disallows for example <code class="docutils literal notranslate"><span class="pre">case</span> <span class="pre">x,</span> <span class="pre">x:</span> <span class="pre">...</span></code> but allows <code class="docutils literal notranslate"><span class="pre">case</span> <span class="pre">[x]</span> <span class="pre">|</span> <span class="pre">x:</span>
<span class="pre">...</span></code>.</p>
</section>
<section id="wildcard-pattern">
<span id="id3"></span><h4><a class="toc-backref" href="#wildcard-pattern" role="doc-backlink">Wildcard Pattern</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">wildcard_pattern</span><span class="p">:</span> <span class="s2">&quot;_&quot;</span>
</pre></div>
</div>
<p>A wildcard pattern always succeeds. It binds no name.</p>
</section>
<section id="value-patterns">
<h4><a class="toc-backref" href="#value-patterns" role="doc-backlink">Value Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">value_pattern</span><span class="p">:</span> <span class="n">attr</span>
<span class="n">attr</span><span class="p">:</span> <span class="n">name_or_attr</span> <span class="s1">&#39;.&#39;</span> <span class="n">NAME</span>
<span class="n">name_or_attr</span><span class="p">:</span> <span class="n">attr</span> <span class="o">|</span> <span class="n">NAME</span>
</pre></div>
</div>
<p>The dotted name in the pattern is looked up using the standard Python
name resolution rules. However, when the same value pattern occurs
multiple times in the same match statement, the interpreter may cache
the first value found and reuse it, rather than repeat the same
lookup. (To clarify, this cache is strictly tied to a given execution
of a given match statement.)</p>
<p>The pattern succeeds if the value found thus compares equal to the
subject value (using the <code class="docutils literal notranslate"><span class="pre">==</span></code> operator).</p>
</section>
<section id="group-patterns">
<h4><a class="toc-backref" href="#group-patterns" role="doc-backlink">Group Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">group_pattern</span><span class="p">:</span> <span class="s1">&#39;(&#39;</span> <span class="n">pattern</span> <span class="s1">&#39;)&#39;</span>
</pre></div>
</div>
<p>(For the syntax of <code class="docutils literal notranslate"><span class="pre">pattern</span></code>, see Patterns above. Note that it
contains no comma a parenthesized series of items with at least one
comma is a sequence pattern, as is <code class="docutils literal notranslate"><span class="pre">()</span></code>.)</p>
<p>A parenthesized pattern has no additional syntax. It allows users to
add parentheses around patterns to emphasize the intended grouping.</p>
</section>
<section id="sequence-patterns">
<span id="sequence-pattern"></span><h4><a class="toc-backref" href="#sequence-patterns" role="doc-backlink">Sequence Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>sequence_pattern:
| &#39;[&#39; [maybe_sequence_pattern] &#39;]&#39;
| &#39;(&#39; [open_sequence_pattern] &#39;)&#39;
open_sequence_pattern: maybe_star_pattern &#39;,&#39; [maybe_sequence_pattern]
maybe_sequence_pattern: &#39;,&#39;.maybe_star_pattern+ &#39;,&#39;?
maybe_star_pattern: star_pattern | pattern
star_pattern: &#39;*&#39; (capture_pattern | wildcard_pattern)
</pre></div>
</div>
<p>(Note that a single parenthesized pattern without a trailing comma is
a group pattern, not a sequence pattern. However a single pattern
enclosed in <code class="docutils literal notranslate"><span class="pre">[...]</span></code> is still a sequence pattern.)</p>
<p>There is no semantic difference between a sequence pattern using
<code class="docutils literal notranslate"><span class="pre">[...]</span></code>, a sequence pattern using <code class="docutils literal notranslate"><span class="pre">(...)</span></code>, and an open sequence
pattern.</p>
<p>A sequence pattern may contain at most one star subpattern. The star
subpattern may occur in any position. If no star subpattern is
present, the sequence pattern is a fixed-length sequence pattern;
otherwise it is a variable-length sequence pattern.</p>
<p>For a sequence pattern to succeed the subject must be a sequence,
where being a sequence is defined as its class being one of the following:</p>
<ul class="simple">
<li>a class that inherits from <code class="docutils literal notranslate"><span class="pre">collections.abc.Sequence</span></code></li>
<li>a Python class that has been registered as a <code class="docutils literal notranslate"><span class="pre">collections.abc.Sequence</span></code></li>
<li>a builtin class that has its <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_SEQUENCE</span></code> bit set</li>
<li>a class that inherits from any of the above (including classes defined <em>before</em> a
parents <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> registration)</li>
</ul>
<p>The following standard library classes will have their <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_SEQUENCE</span></code>
bit set:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">array.array</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">collections.deque</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">list</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">memoryview</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">range</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">tuple</span></code></li>
</ul>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Although <code class="docutils literal notranslate"><span class="pre">str</span></code>, <code class="docutils literal notranslate"><span class="pre">bytes</span></code>, and <code class="docutils literal notranslate"><span class="pre">bytearray</span></code> are usually
considered sequences, they are not included in the above list and do
not match sequence patterns.</p>
</div>
<p>A fixed-length sequence pattern fails if the length of the subject
sequence is not equal to the number of subpatterns.</p>
<p>A variable-length sequence pattern fails if the length of the subject
sequence is less than the number of non-star subpatterns.</p>
<p>The length of the subject sequence is obtained using the builtin
<code class="docutils literal notranslate"><span class="pre">len()</span></code> function (i.e., via the <code class="docutils literal notranslate"><span class="pre">__len__</span></code> protocol). However, the
interpreter may cache this value in a similar manner as described for
value patterns.</p>
<p>A fixed-length sequence pattern matches the subpatterns to
corresponding items of the subject sequence, from left to right.
Matching stops (with a failure) as soon as a subpattern fails. If all
subpatterns succeed in matching their corresponding item, the sequence
pattern succeeds.</p>
<p>A variable-length sequence pattern first matches the leading non-star
subpatterns to the corresponding items of the subject sequence, as for
a fixed-length sequence. If this succeeds, the star subpattern
matches a list formed of the remaining subject items, with items
removed from the end corresponding to the non-star subpatterns
following the star subpattern. The remaining non-star subpatterns are
then matched to the corresponding subject items, as for a fixed-length
sequence.</p>
</section>
<section id="mapping-patterns">
<span id="mapping-pattern"></span><h4><a class="toc-backref" href="#mapping-patterns" role="doc-backlink">Mapping Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>mapping_pattern: &#39;{&#39; [items_pattern] &#39;}&#39;
items_pattern: &#39;,&#39;.key_value_pattern+ &#39;,&#39;?
key_value_pattern:
| (literal_pattern | value_pattern) &#39;:&#39; pattern
| double_star_pattern
double_star_pattern: &#39;**&#39; capture_pattern
</pre></div>
</div>
<p>(Note that <code class="docutils literal notranslate"><span class="pre">**_</span></code> is disallowed by this syntax.)</p>
<p>A mapping pattern may contain at most one double star pattern,
and it must be last.</p>
<p>A mapping pattern may not contain duplicate key values.
(If all key patterns are literal patterns this is considered a
syntax error; otherwise this is a runtime error and will
raise <code class="docutils literal notranslate"><span class="pre">ValueError</span></code>.)</p>
<p>For a mapping pattern to succeed the subject must be a mapping,
where being a mapping is defined as its class being one of the following:</p>
<ul class="simple">
<li>a class that inherits from <code class="docutils literal notranslate"><span class="pre">collections.abc.Mapping</span></code></li>
<li>a Python class that has been registered as a <code class="docutils literal notranslate"><span class="pre">collections.abc.Mapping</span></code></li>
<li>a builtin class that has its <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_MAPPING</span></code> bit set</li>
<li>a class that inherits from any of the above (including classes defined <em>before</em> a
parents <code class="docutils literal notranslate"><span class="pre">Mapping</span></code> registration)</li>
</ul>
<p>The standard library classes <code class="docutils literal notranslate"><span class="pre">dict</span></code> and <code class="docutils literal notranslate"><span class="pre">mappingproxy</span></code> will have their <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_MAPPING</span></code>
bit set.</p>
<p>A mapping pattern succeeds if every key given in the mapping pattern
is present in the subject mapping, and the pattern for
each key matches the corresponding item of the subject mapping. Keys
are always compared with the <code class="docutils literal notranslate"><span class="pre">==</span></code> operator. If a <code class="docutils literal notranslate"><span class="pre">'**'</span>
<span class="pre">NAME</span></code> form is present, that name is bound to a <code class="docutils literal notranslate"><span class="pre">dict</span></code> containing
remaining key-value pairs from the subject mapping.</p>
<p>If duplicate keys are detected in the mapping pattern, the pattern is
considered invalid, and a <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> is raised.</p>
<p>Key-value pairs are matched using the two-argument form of the
subjects <code class="docutils literal notranslate"><span class="pre">get()</span></code> method. As a consequence, matched key-value pairs
must already be present in the mapping, and not created on-the-fly by
<code class="docutils literal notranslate"><span class="pre">__missing__</span></code> or <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code>. For example,
<code class="docutils literal notranslate"><span class="pre">collections.defaultdict</span></code> instances will only be matched by patterns
with keys that were already present when the match statement was
entered.</p>
</section>
<section id="class-patterns">
<span id="class-pattern"></span><h4><a class="toc-backref" href="#class-patterns" role="doc-backlink">Class Patterns</a></h4>
<p>Syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>class_pattern:
| name_or_attr &#39;(&#39; [pattern_arguments &#39;,&#39;?] &#39;)&#39;
pattern_arguments:
| positional_patterns [&#39;,&#39; keyword_patterns]
| keyword_patterns
positional_patterns: &#39;,&#39;.pattern+
keyword_patterns: &#39;,&#39;.keyword_pattern+
keyword_pattern: NAME &#39;=&#39; pattern
</pre></div>
</div>
<p>A class pattern may not repeat the same keyword multiple times.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">name_or_attr</span></code> is not an instance of the builtin <code class="docutils literal notranslate"><span class="pre">type</span></code>,
<code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</p>
<p>A class pattern fails if the subject is not an instance of <code class="docutils literal notranslate"><span class="pre">name_or_attr</span></code>.
This is tested using <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code>.</p>
<p>If no arguments are present, the pattern succeeds if the <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code>
check succeeds. Otherwise:</p>
<ul class="simple">
<li>If only keyword patterns are present, they are processed as follows,
one by one:<ul>
<li>The keyword is looked up as an attribute on the subject.<ul>
<li>If this raises an exception other than <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code>,
the exception bubbles up.</li>
<li>If this raises <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code> the class pattern fails.</li>
<li>Otherwise, the subpattern associated with the keyword is matched
against the attribute value. If this fails, the class pattern fails.
If it succeeds, the match proceeds to the next keyword.</li>
</ul>
</li>
<li>If all keyword patterns succeed, the class pattern as a whole succeeds.</li>
</ul>
</li>
<li>If any positional patterns are present, they are converted to keyword
patterns (see below) and treated as additional keyword patterns,
preceding the syntactic keyword patterns (if any).</li>
</ul>
<p>Positional patterns are converted to keyword patterns using the
<code class="docutils literal notranslate"><span class="pre">__match_args__</span></code> attribute on the class designated by <code class="docutils literal notranslate"><span class="pre">name_or_attr</span></code>,
as follows:</p>
<ul class="simple">
<li>For a number of built-in types (specified below),
a single positional subpattern is accepted which will match
the entire subject. (Keyword patterns work as for other types here.)</li>
<li>The equivalent of <code class="docutils literal notranslate"><span class="pre">getattr(cls,</span> <span class="pre">&quot;__match_args__&quot;,</span> <span class="pre">()))</span></code> is called.</li>
<li>If this raises an exception the exception bubbles up.</li>
<li>If the returned value is not a tuple, the conversion fails
and <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</li>
<li>If there are more positional patterns than the length of
<code class="docutils literal notranslate"><span class="pre">__match_args__</span></code> (as obtained using <code class="docutils literal notranslate"><span class="pre">len()</span></code>), <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</li>
<li>Otherwise, positional pattern <code class="docutils literal notranslate"><span class="pre">i</span></code> is converted to a keyword pattern
using <code class="docutils literal notranslate"><span class="pre">__match_args__[i]</span></code> as the keyword,
provided it the latter is a string;
if it is not, <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</li>
<li>For duplicate keywords, <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</li>
</ul>
<p>Once the positional patterns have been converted to keyword patterns,
the match proceeds as if there were only keyword patterns.</p>
<p>As mentioned above, for the following built-in types the handling of
positional subpatterns is different:
<code class="docutils literal notranslate"><span class="pre">bool</span></code>, <code class="docutils literal notranslate"><span class="pre">bytearray</span></code>, <code class="docutils literal notranslate"><span class="pre">bytes</span></code>, <code class="docutils literal notranslate"><span class="pre">dict</span></code>, <code class="docutils literal notranslate"><span class="pre">float</span></code>,
<code class="docutils literal notranslate"><span class="pre">frozenset</span></code>, <code class="docutils literal notranslate"><span class="pre">int</span></code>, <code class="docutils literal notranslate"><span class="pre">list</span></code>, <code class="docutils literal notranslate"><span class="pre">set</span></code>, <code class="docutils literal notranslate"><span class="pre">str</span></code>, and <code class="docutils literal notranslate"><span class="pre">tuple</span></code>.</p>
<p>This behavior is roughly equivalent to the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">__match_args__</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;__match_self_prop__&quot;</span><span class="p">,)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">__match_self_prop__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span>
</pre></div>
</div>
</section>
</section>
</section>
<section id="side-effects-and-undefined-behavior">
<h2><a class="toc-backref" href="#side-effects-and-undefined-behavior" role="doc-backlink">Side Effects and Undefined Behavior</a></h2>
<p>The only side-effect produced explicitly by the matching process is
the binding of names. However, the process relies on attribute
access, instance checks, <code class="docutils literal notranslate"><span class="pre">len()</span></code>, equality and item access on the
subject and some of its components. It also evaluates value
patterns and the class name of class patterns. While none of those
typically create any side-effects, in theory they could. This
proposal intentionally leaves out any specification of what methods
are called or how many times. This behavior is therefore undefined
and user code should not rely on it.</p>
<p>Another undefined behavior is the binding of variables by capture
patterns that are followed (in the same case block) by another pattern
that fails. These may happen earlier or later depending on the
implementation strategy, the only constraint being that capture
variables must be set before guards that use them explicitly are
evaluated. If a guard consists of an <code class="docutils literal notranslate"><span class="pre">and</span></code> clause, evaluation of
the operands may even be interspersed with pattern matching, as long
as left-to-right evaluation order is maintained.</p>
</section>
<section id="the-standard-library">
<h2><a class="toc-backref" href="#the-standard-library" role="doc-backlink">The Standard Library</a></h2>
<p>To facilitate the use of pattern matching, several changes will be
made to the standard library:</p>
<ul class="simple">
<li>Namedtuples and dataclasses will have auto-generated
<code class="docutils literal notranslate"><span class="pre">__match_args__</span></code>.</li>
<li>For dataclasses the order of attributes in the generated
<code class="docutils literal notranslate"><span class="pre">__match_args__</span></code> will be the same as the order of corresponding
arguments in the generated <code class="docutils literal notranslate"><span class="pre">__init__()</span></code> method. This includes the
situations where attributes are inherited from a superclass. Fields
with <code class="docutils literal notranslate"><span class="pre">init=False</span></code> are excluded from <code class="docutils literal notranslate"><span class="pre">__match_args__</span></code>.</li>
</ul>
<p>In addition, a systematic effort will be put into going through
existing standard library classes and adding <code class="docutils literal notranslate"><span class="pre">__match_args__</span></code> where
it looks beneficial.</p>
</section>
<section id="appendix-a-full-grammar">
<span id="appendix-a"></span><h2><a class="toc-backref" href="#appendix-a-full-grammar" role="doc-backlink">Appendix A Full Grammar</a></h2>
<p>Here is the full grammar for <code class="docutils literal notranslate"><span class="pre">match_stmt</span></code>. This is an additional
alternative for <code class="docutils literal notranslate"><span class="pre">compound_stmt</span></code>. Remember that <code class="docutils literal notranslate"><span class="pre">match</span></code> and
<code class="docutils literal notranslate"><span class="pre">case</span></code> are soft keywords, i.e. they are not reserved words in other
grammatical contexts (including at the start of a line if there is no
colon where expected). By convention, hard keywords use single quotes
while soft keywords use double quotes.</p>
<p>Other notation used beyond standard EBNF:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">SEP.RULE+</span></code> is shorthand for <code class="docutils literal notranslate"><span class="pre">RULE</span> <span class="pre">(SEP</span> <span class="pre">RULE)*</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">!RULE</span></code> is a negative lookahead assertion</li>
</ul>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>match_stmt: &quot;match&quot; subject_expr &#39;:&#39; NEWLINE INDENT case_block+ DEDENT
subject_expr:
| star_named_expression &#39;,&#39; [star_named_expressions]
| named_expression
case_block: &quot;case&quot; patterns [guard] &#39;:&#39; block
guard: &#39;if&#39; named_expression
patterns: open_sequence_pattern | pattern
pattern: as_pattern | or_pattern
as_pattern: or_pattern &#39;as&#39; capture_pattern
or_pattern: &#39;|&#39;.closed_pattern+
closed_pattern:
| literal_pattern
| capture_pattern
| wildcard_pattern
| value_pattern
| group_pattern
| sequence_pattern
| mapping_pattern
| class_pattern
literal_pattern:
| signed_number !(&#39;+&#39; | &#39;-&#39;)
| signed_number &#39;+&#39; NUMBER
| signed_number &#39;-&#39; NUMBER
| strings
| &#39;None&#39;
| &#39;True&#39;
| &#39;False&#39;
signed_number: NUMBER | &#39;-&#39; NUMBER
capture_pattern: !&quot;_&quot; NAME !(&#39;.&#39; | &#39;(&#39; | &#39;=&#39;)
wildcard_pattern: &quot;_&quot;
value_pattern: attr !(&#39;.&#39; | &#39;(&#39; | &#39;=&#39;)
attr: name_or_attr &#39;.&#39; NAME
name_or_attr: attr | NAME
group_pattern: &#39;(&#39; pattern &#39;)&#39;
sequence_pattern:
| &#39;[&#39; [maybe_sequence_pattern] &#39;]&#39;
| &#39;(&#39; [open_sequence_pattern] &#39;)&#39;
open_sequence_pattern: maybe_star_pattern &#39;,&#39; [maybe_sequence_pattern]
maybe_sequence_pattern: &#39;,&#39;.maybe_star_pattern+ &#39;,&#39;?
maybe_star_pattern: star_pattern | pattern
star_pattern: &#39;*&#39; (capture_pattern | wildcard_pattern)
mapping_pattern: &#39;{&#39; [items_pattern] &#39;}&#39;
items_pattern: &#39;,&#39;.key_value_pattern+ &#39;,&#39;?
key_value_pattern:
| (literal_pattern | value_pattern) &#39;:&#39; pattern
| double_star_pattern
double_star_pattern: &#39;**&#39; capture_pattern
class_pattern:
| name_or_attr &#39;(&#39; [pattern_arguments &#39;,&#39;?] &#39;)&#39;
pattern_arguments:
| positional_patterns [&#39;,&#39; keyword_patterns]
| keyword_patterns
positional_patterns: &#39;,&#39;.pattern+
keyword_patterns: &#39;,&#39;.keyword_pattern+
keyword_pattern: NAME &#39;=&#39; pattern
</pre></div>
</div>
</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-0634.rst">https://github.com/python/peps/blob/main/peps/pep-0634.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0634.rst">2023-12-11 05:40:56 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="#syntax-and-semantics">Syntax and Semantics</a><ul>
<li><a class="reference internal" href="#overview-and-terminology">Overview and Terminology</a></li>
<li><a class="reference internal" href="#the-match-statement">The Match Statement</a><ul>
<li><a class="reference internal" href="#match-semantics">Match Semantics</a></li>
<li><a class="reference internal" href="#guards">Guards</a></li>
<li><a class="reference internal" href="#irrefutable-case-blocks">Irrefutable case blocks</a></li>
</ul>
</li>
<li><a class="reference internal" href="#patterns">Patterns</a><ul>
<li><a class="reference internal" href="#as-patterns">AS Patterns</a></li>
<li><a class="reference internal" href="#or-patterns">OR Patterns</a></li>
<li><a class="reference internal" href="#literal-patterns">Literal Patterns</a></li>
<li><a class="reference internal" href="#capture-patterns">Capture Patterns</a></li>
<li><a class="reference internal" href="#wildcard-pattern">Wildcard Pattern</a></li>
<li><a class="reference internal" href="#value-patterns">Value Patterns</a></li>
<li><a class="reference internal" href="#group-patterns">Group Patterns</a></li>
<li><a class="reference internal" href="#sequence-patterns">Sequence Patterns</a></li>
<li><a class="reference internal" href="#mapping-patterns">Mapping Patterns</a></li>
<li><a class="reference internal" href="#class-patterns">Class Patterns</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#side-effects-and-undefined-behavior">Side Effects and Undefined Behavior</a></li>
<li><a class="reference internal" href="#the-standard-library">The Standard Library</a></li>
<li><a class="reference internal" href="#appendix-a-full-grammar">Appendix A Full Grammar</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-0634.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>