Updates to PEP 505 (#697)
This commit is contained in:
parent
33877f7ac3
commit
e89685036f
|
@ -3,7 +3,7 @@ Title: None-aware operators
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Mark E. Haase <mehaase@gmail.com>, Steve Dower <steve.dower@python.org>
|
Author: Mark E. Haase <mehaase@gmail.com>, Steve Dower <steve.dower@python.org>
|
||||||
Status: Deferred
|
Status: Draft
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/x-rst
|
Content-Type: text/x-rst
|
||||||
Created: 18-Sep-2015
|
Created: 18-Sep-2015
|
||||||
|
@ -60,18 +60,22 @@ Grammar changes
|
||||||
|
|
||||||
The following rules of the Python grammar are updated to read::
|
The following rules of the Python grammar are updated to read::
|
||||||
|
|
||||||
power: coalesce_expr ['**' factor]
|
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
|
||||||
coalesce_expr: atom_expr ['??' atom_expr]
|
'<<=' | '>>=' | '**=' | '//=' | '??=')
|
||||||
atom_expr: ['await'] atom trailer*
|
term: coalesce (('*'|'@'|'/'|'%'|'//') coalesce)*
|
||||||
trailer: '(' [arglist] ')' |
|
coalesce: factor ('??' factor)*
|
||||||
'[' subscriptlist ']' |
|
|
||||||
'?[' subscriptlist ']' |
|
|
||||||
'.' NAME |
|
|
||||||
'?.' NAME
|
|
||||||
|
|
||||||
Inserting the ``coalesce_expr`` rule in this location ensures that
|
# factor eventually resolved to atom_expr
|
||||||
expressions resulting in ``None`` are natuarlly coalesced before they are used
|
atom_expr: ['await'] atom trailer*
|
||||||
in operations that would typically raise ``TypeError``. Like ``and`` and ``or``
|
trailer: ('(' [arglist] ')' |
|
||||||
|
'[' subscriptlist ']' |
|
||||||
|
'?[' subscriptlist ']' |
|
||||||
|
'.' NAME |
|
||||||
|
'?.' NAME)
|
||||||
|
|
||||||
|
Inserting the ``coalesce`` rule in this location ensures that expressions
|
||||||
|
resulting in ``None`` are natuarlly coalesced before they are used in
|
||||||
|
operations that would typically raise ``TypeError``. Like ``and`` and ``or``
|
||||||
the right-hand expression is not evaluated until the left-hand side is
|
the right-hand expression is not evaluated until the left-hand side is
|
||||||
determined to be ``None``. For example::
|
determined to be ``None``. For example::
|
||||||
|
|
||||||
|
@ -79,16 +83,31 @@ determined to be ``None``. For example::
|
||||||
def c(): return None
|
def c(): return None
|
||||||
def ex(): raise Exception()
|
def ex(): raise Exception()
|
||||||
|
|
||||||
(a ?? 2 ** b ?? 3) == (a ?? 2) ** (b ?? 3)
|
(a ?? 2 ** b ?? 3) == a ?? (2 ** b) ?? 3
|
||||||
|
(a * b ?? c // d) == (a * b) ?? (c // d)
|
||||||
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
|
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
|
||||||
(c() ?? c() ?? True) == True
|
(c() ?? c() ?? True) == True
|
||||||
(True ?? ex()) == True
|
(True ?? ex()) == True
|
||||||
(c ?? ex)() == c()
|
(c ?? ex)() == c()
|
||||||
|
|
||||||
|
Augmented coalescing assignment only rebinds the name if its current value is
|
||||||
|
``None``. If the target name already has a value, the right-hand side is not
|
||||||
|
evaluated. For example::
|
||||||
|
|
||||||
|
a = None
|
||||||
|
b = ''
|
||||||
|
|
||||||
|
a ??= 'value'
|
||||||
|
b ??= undefined_name
|
||||||
|
|
||||||
|
assert a == 'value'
|
||||||
|
assert b == ''
|
||||||
|
|
||||||
Adding new trailers for the other ``None``-aware operators ensures that they
|
Adding new trailers for the other ``None``-aware operators ensures that they
|
||||||
may be used in all valid locations for the existing equivalent operators.
|
may be used in all valid locations for the existing equivalent operators,
|
||||||
However, as the existing evaluation rules are not directly embedded in the
|
including as part of an assignment target (more details below). As the existing
|
||||||
grammar, we specify the required changes here.
|
evaluation rules are not directly embedded in the grammar, we specify the
|
||||||
|
required changes here.
|
||||||
|
|
||||||
Assume that the ``atom`` is always successfully evaluated. Each ``trailer`` is
|
Assume that the ``atom`` is always successfully evaluated. Each ``trailer`` is
|
||||||
then evaluated from left to right, applying its own parameter (either its
|
then evaluated from left to right, applying its own parameter (either its
|
||||||
|
@ -143,6 +162,14 @@ transformation. For example, ``(a?.b ?? c).d?.e`` is evaluated as::
|
||||||
if _v is not None:
|
if _v is not None:
|
||||||
_v = _v.e
|
_v = _v.e
|
||||||
|
|
||||||
|
When used as an assignment target, the ``None``-aware operations may only be
|
||||||
|
used in a "load" context. That is, ``a?.b = 1`` and ``a?[b] = 1`` will raise
|
||||||
|
``SyntaxError``. Use earlier in the expression (``a?.b.c = 1``) is permitted,
|
||||||
|
though unlikely to be useful unless combined with a coalescing operation::
|
||||||
|
|
||||||
|
(a?.b ?? d).c = 1
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
========
|
========
|
||||||
|
|
Loading…
Reference in New Issue