PEP 653: Fix example. Use get(key, sentinel) instead of __getitem__(key) for mappings. (#1902)

This commit is contained in:
Mark Shannon 2021-03-30 23:30:43 +01:00 committed by GitHub
parent 0a0e7a3045
commit c029c02e36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 21 additions and 14 deletions

View File

@ -53,7 +53,7 @@ By allowing classes to choose which kinds of pattern they match, other classes c
For example, using ``sympy``, we might want to write:: For example, using ``sympy``, we might want to write::
# a*a == a**2 # a*a == a**2
case Mul(args=[a, b]) if a == b: case Mul(args=[Symbol(a), Symbol(b)]) if a == b:
return Pow(a, 2) return Pow(a, 2)
Which requires the sympy class ``Symbol`` to "self" match. Which requires the sympy class ``Symbol`` to "self" match.
@ -273,14 +273,16 @@ A pattern not including a double-star pattern::
translates to:: translates to::
$sentinel = object()
$kind = type($value).__match_container__ $kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0: if $kind & MATCH_MAPPING == 0:
FAIL FAIL
if not $value.keys() >= $KEYWORD_PATTERNS.keys():
FAIL
# $KEYWORD_PATTERNS is a meta-variable mapping names to variables. # $KEYWORD_PATTERNS is a meta-variable mapping names to variables.
for $KEYWORD in $KEYWORD_PATTERNS: for $KEYWORD in $KEYWORD_PATTERNS:
$KEYWORD_PATTERNS[$KEYWORD] = $value[QUOTE($KEYWORD)] $tmp = $value.get(QUOTE($KEYWORD), $sentinel)
if $tmp is $sentinel:
FAIL
$KEYWORD_PATTERNS[$KEYWORD] = $tmp
Example: [4]_ Example: [4]_
@ -293,10 +295,10 @@ translates to::
$kind = type($value).__match_container__ $kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0: if $kind & MATCH_MAPPING == 0:
FAIL FAIL
if not $value.keys() >= $KEYWORD_PATTERNS.keys():
FAIL:
# $KEYWORD_PATTERNS is a meta-variable mapping names to variables. # $KEYWORD_PATTERNS is a meta-variable mapping names to variables.
$tmp = dict($value) $tmp = dict($value)
if not $tmp.keys() >= $KEYWORD_PATTERNS.keys():
FAIL:
for $KEYWORD in $KEYWORD_PATTERNS: for $KEYWORD in $KEYWORD_PATTERNS:
$KEYWORD_PATTERNS[$KEYWORD] = $tmp.pop(QUOTE($KEYWORD)) $KEYWORD_PATTERNS[$KEYWORD] = $tmp.pop(QUOTE($KEYWORD))
$DOUBLE_STARRED_PATTERN = $tmp $DOUBLE_STARRED_PATTERN = $tmp
@ -502,15 +504,14 @@ on the naive implementation.
When performing matching, implementations are allowed When performing matching, implementations are allowed
to treat the following functions and methods as pure: to treat the following functions and methods as pure:
For any class supporting ``MATCH_SEQUENCE`` or ``MATCH_MAPPING``:: For any class supporting ``MATCH_SEQUENCE``::
* ``cls.__len__()`` * ``cls.__len__()``
* ``cls.__getitem__()`` * ``cls.__getitem__()``
For any class supporting ``MATCH_MAPPING``:: For any class supporting ``MATCH_MAPPING``::
* ``cls.keys()`` * ``cls.get()`` (Two argument form only)
* ``cls.__contains__()``
Implementations are allowed to make the following assumptions: Implementations are allowed to make the following assumptions:
@ -519,6 +520,8 @@ Implementations are allowed to make the following assumptions:
* Reading any of ``__match_container__``, ``__match_class__`` or ``__match_args__`` is a pure operation, and may be cached. * Reading any of ``__match_container__``, ``__match_class__`` or ``__match_args__`` is a pure operation, and may be cached.
* Sequences, that is any class for which ``__match_container__&MATCH_SEQUENCE`` is not zero, are not modified by iteration, subscripting or calls to ``len()``. * Sequences, that is any class for which ``__match_container__&MATCH_SEQUENCE`` is not zero, are not modified by iteration, subscripting or calls to ``len()``.
Consequently, those operations can be freely substituted for each other where they would be equivalent when applied to an immutable sequence. Consequently, those operations can be freely substituted for each other where they would be equivalent when applied to an immutable sequence.
* Mappings, that is any class for which ``__match_container__&MATCH_MAPPING`` is not zero, will not capture the second argument of the ``get()`` method.
So, the ``$sentinel`` value may be freely re-used.
In fact, implementations are encouraged to make these assumptions, as it is likely to result in signficantly better performance. In fact, implementations are encouraged to make these assumptions, as it is likely to result in signficantly better performance.
@ -779,10 +782,14 @@ translates to::
$kind = type($value).__match_container__ $kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0: if $kind & MATCH_MAPPING == 0:
FAIL FAIL
if $value.keys() != {"x", "y"}: $tmp = $value.get("x", $sentinel)
if $tmp is $sentinel:
FAIL FAIL
x = $value["x"] x = $tmp
y = $value["y"] $tmp = $value.get("y", $sentinel)
if $tmp is $sentinel:
FAIL
y = $tmp
if not x > 2: if not x > 2:
FAIL FAIL
@ -797,9 +804,9 @@ translates to::
$kind = type($value).__match_container__ $kind = type($value).__match_container__
if $kind & MATCH_MAPPING == 0: if $kind & MATCH_MAPPING == 0:
FAIL FAIL
if not $value.keys() >= {"x", "y"}:
FAIL
$tmp = dict($value) $tmp = dict($value)
if not $tmp.keys() >= {"x", "y"}:
FAIL
x = $tmp.pop("x") x = $tmp.pop("x")
y = $tmp.pop("y") y = $tmp.pop("y")
z = $tmp z = $tmp