|
| 1 | +PEP: 991 |
| 2 | +Title: Extend match value pattern to support names |
| 3 | +Author: Marc Mueller |
| 4 | +Sponsor: TODO |
| 5 | +Discussions-To: Pending |
| 6 | +Status: Draft |
| 7 | +Type: Standards Track |
| 8 | +Created: 2026-07-07 |
| 9 | +Python-Version: 3.16 |
| 10 | + |
| 11 | + |
| 12 | +Abstract |
| 13 | +======== |
| 14 | + |
| 15 | +[A short (~200 word) description of the technical issue being addressed.] |
| 16 | + |
| 17 | + |
| 18 | +Motivation |
| 19 | +========== |
| 20 | + |
| 21 | +When the match statement was proposed in |
| 22 | +`PEP 634 <https://peps.python.org/pep-0634/#value-patterns>`_, |
| 23 | +the decision was made to only support dotted names, i.e. attributes, |
| 24 | +in value patterns because for simple names it is not possible to |
| 25 | +differentiate them from capture patterns. The current workaround for |
| 26 | +this limitation is to combine a name capture pattern with an explicit |
| 27 | +guard clause. |
| 28 | + |
| 29 | +.. code-block:: python |
| 30 | +
|
| 31 | + books: dict[str, str] |
| 32 | +
|
| 33 | + def get_book_titles_for_author(author: str): |
| 34 | + for book in books: |
| 35 | + match book: |
| 36 | + case ( |
| 37 | + {"title": title, "author": book_author} |
| 38 | + if book_author == author |
| 39 | + ): |
| 40 | + yield title |
| 41 | +
|
| 42 | +While this works, it is unnecessarily difficult to read and write, |
| 43 | +especially if the match cases get more complex. Furthermore, it has |
| 44 | +some additional limitations: |
| 45 | + |
| 46 | +- As a workaround, it might not taught together with the value pattern. |
| 47 | + In particular developers new to the match statement might find it |
| 48 | + difficult to come up with at first. |
| 49 | + |
| 50 | +- The guard clause is separate from the value pattern. For deeply |
| 51 | + nested patterns, this increases the complexity while reading the |
| 52 | + match case. It is necessary to keep track of all capture patterns |
| 53 | + mentally just for it to be used in the guard clause. At which point |
| 54 | + it is not obvious whether or not the name is also used in the case |
| 55 | + body as well. |
| 56 | + |
| 57 | +- The name being checked is often closely related or even the same as |
| 58 | + the variable. In the example above both are ``author``. This makes |
| 59 | + it necessary to choose a different, suboptimal name for the name |
| 60 | + capture only to avoid accidentally overwriting the variable. |
| 61 | + |
| 62 | +- Due to the similar names, it is also frequently not possible to |
| 63 | + know by only reading the guard clause which is the name and which |
| 64 | + the variable being checked. |
| 65 | + |
| 66 | +- Combining the workaround with ``OR`` patterns is limited because |
| 67 | + these require that name captures are defined in **all** alternatives. |
| 68 | + This can make it necessary to duplicate the case body if an |
| 69 | + alternative does not need the name capture. |
| 70 | + |
| 71 | +- The guard clause is only checked after the pattern itself matches. |
| 72 | + Especially for complex patterns, this can lead to unnecessary work |
| 73 | + when the name capture is followed by other patterns. As the capture |
| 74 | + always succeeds, the other patterns are evaluated even if it is |
| 75 | + obvious to the outside observer that the guard will fail. |
| 76 | + |
| 77 | +This PEP picks up on a deferred suggestion from |
| 78 | +`PEP 635 <https://peps.python.org/pep-0635/#value-patterns>`_ to use |
| 79 | +a leading dot for value patterns with names. The example above could |
| 80 | +then be written as: |
| 81 | + |
| 82 | +.. code-block:: python |
| 83 | +
|
| 84 | + def get_book_titles_for_author(author: str): |
| 85 | + for book in books: |
| 86 | + match book: |
| 87 | + case {"title": title, "author": .author}: |
| 88 | + yield title |
| 89 | +
|
| 90 | +.. TODO sentinels + direct name imports |
| 91 | +
|
| 92 | +
|
| 93 | +Specification |
| 94 | +============= |
| 95 | + |
| 96 | +The value pattern will be extended to support simple names, besides |
| 97 | +attributes, if they are prefixed by a leading dot. The lookup is |
| 98 | +performed following the standard Python name resolution rules. |
| 99 | + |
| 100 | +Grammar changes |
| 101 | +--------------- |
| 102 | + |
| 103 | +The ``value_pattern`` rule is extended to support names prefixed by |
| 104 | +a leading dot. |
| 105 | + |
| 106 | +.. code-block:: PEG |
| 107 | +
|
| 108 | + value_pattern: |
| 109 | + | attr=attr !('.' | '(' | '=') |
| 110 | + | '.' name=NAME |
| 111 | +
|
| 112 | +
|
| 113 | +Rationale |
| 114 | +========= |
| 115 | + |
| 116 | +`PEP 635 <https://peps.python.org/pep-0635/#value-patterns>`_ |
| 117 | +acknowledged that only supporting dotted names, i.e. attributes, |
| 118 | +for the value pattern would preclude local and global variables |
| 119 | +from acting as constants inside match patterns. While a workaround |
| 120 | +exists, it has its own limitations as shown in the `Motivation`_ |
| 121 | +section. Extending the value pattern using the leading dot rule |
| 122 | +will make it easier to read and write match statements. |
| 123 | + |
| 124 | +The leading dot was chosen as it is the most natural extension of |
| 125 | +the existing value pattern rule. Simple names cannot be used since |
| 126 | +they already represent capture patterns. The main point of concern |
| 127 | +was that ``.`` might be too easily missed. So a multitude of |
| 128 | +alternatives have been proposed. See `Alternative syntax proposals`_ |
| 129 | +in the rejected ideas section for discussion why those were not chosen |
| 130 | +instead. However, a quick poll [#poll]_ on discuss.python.org |
| 131 | +suggests that a majority prefers the leading dot. The author believes |
| 132 | +that the improvement from not having to write a separate guard |
| 133 | +clause and matching the variable inside the pattern directly, |
| 134 | +is worth it compared to the small readability concern. |
| 135 | + |
| 136 | + |
| 137 | +Backwards Compatibility |
| 138 | +======================= |
| 139 | + |
| 140 | +The change is fully backwards compatible. So far using ``.name`` |
| 141 | +raised a ``SyntaxError``. |
| 142 | + |
| 143 | + |
| 144 | +Security Implications |
| 145 | +===================== |
| 146 | + |
| 147 | +There are no new security implications from this proposal. |
| 148 | + |
| 149 | + |
| 150 | +How to Teach This |
| 151 | +================= |
| 152 | + |
| 153 | +[How to teach users, new and experienced, how to apply the PEP to their work.] |
| 154 | + |
| 155 | + |
| 156 | +Reference Implementation |
| 157 | +======================== |
| 158 | + |
| 159 | +.. TODO update links |
| 160 | +
|
| 161 | +A reference implementation is available at |
| 162 | +https://github.com/cdce8p/cpython/tree/<TODO>. |
| 163 | +A online demo can be tested at https://<TODO>-demo.pages.dev/. |
| 164 | + |
| 165 | + |
| 166 | +Rejected Ideas |
| 167 | +============== |
| 168 | + |
| 169 | +Alternative syntax proposals |
| 170 | +---------------------------- |
| 171 | + |
| 172 | +.. TODO |
| 173 | +
|
| 174 | +
|
| 175 | +Footnotes |
| 176 | +========= |
| 177 | + |
| 178 | +.. [#poll] discuss.python.org: Poll comparing different syntax proposals |
| 179 | + (https://discuss.python.org/t/pattern-matching-on-constants-that-arent-in-a-namespace-especially-sentinels/107916/61) |
| 180 | +
|
| 181 | +
|
| 182 | +Copyright |
| 183 | +========= |
| 184 | + |
| 185 | +This document is placed in the public domain or under the |
| 186 | +CC0-1.0-Universal license, whichever is more permissive. |
0 commit comments