@@ -39,7 +39,7 @@ An attribute or value is ``optional``
3939 In the context of this PEP an attribute or value is considered
4040 ``optional `` if it is always present but can be ``None ``.
4141
42- .. code-block :: python
42+ .. code-block :: python-console
4343
4444 >>> class A:
4545 ... def __init__(self, val: int | None) -> None:
@@ -54,7 +54,7 @@ An attribute or value is ``missing``
5454 at all. For ``typing.TypedDict `` these would be ``typing.NotRequired ``
5555 keys when they are not preset.
5656
57- .. code-block :: python
57+ .. code-block :: python-console
5858
5959 >>> class A:
6060 ... val: int | None
@@ -240,13 +240,17 @@ To start, assume each attribute, subscript and function call is
240240
241241 Now insert ``? `` after each ``optional `` subexpression. IDEs and most
242242type checkers will be able to help with identifying these. *Spaces added
243- for clarity only, though still valid *::
243+ for clarity only, though still valid *:
244+
245+ ::
244246
245247 def get_person_email(sensor: Sensor) -> str | None:
246248 return sensor.machine? .line? .department.engineer? .email? [0]
247249 # ^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^^
248250
249- The complete function would then be::
251+ The complete function would then be:
252+
253+ ::
250254
251255 def get_person_email(sensor: Sensor) -> str | None:
252256 return sensor.machine?.line?.department.engineer?.email?[0]
@@ -588,7 +592,9 @@ Grammar changes
588592---------------
589593
590594A new ``? `` token is added. In addition the ``primary `` grammar rule is
591- updated to include ``none_aware_attribute `` and ``none_aware_subscript ``::
595+ updated to include ``none_aware_attribute `` and ``none_aware_subscript ``.
596+
597+ .. code-block :: PEG
592598
593599 primary:
594600 | primary '.' NAME
@@ -751,8 +757,8 @@ defined. Only ``a``, ``.c`` and ``.d`` are expected to possibly be ``None``.
751757If ``.b `` all of the sudden is also ``None ``, it would still raise an
752758``AttributeError `` since it was unexpected. That would not happen for
753759``maybe ``. This behavior is problematic since it can subtly hide real
754- issues. As the expression output can already be ``None `` the space of
755- potential output didn't change and as such no error would appear.
760+ issues. As the expression output can already be ``None ``, the space of
761+ potential outputs didn't change and as such no error would appear.
756762
757763If it is the intend to catch all ``AttributeError `` and ``TypeError ``,
758764a try-except block can be used instead.
@@ -797,7 +803,9 @@ operators introduced, a unary, postfix operator ``?`` was considered.
797803While this might have made teaching the operators a bit easier, just one
798804instead of two new operators, it may also be **too general **, in a sense
799805that it can be combine with any other operator. For example it is not
800- clear what the following expressions would mean::
806+ clear what the following expressions would mean:
807+
808+ ::
801809
802810 >>> x? + 1
803811 >>> x? -= 1
@@ -819,7 +827,7 @@ values in nested objects with ``optional`` attributes.
819827
820828If future PEPs want to introduce new operators to access attributes or
821829call methods, e.g. a chaining operator, it would be advisable to consider
822- if a ``None ``-aware variant for it could be useful at that time.
830+ if a ``None ``-aware variant for it could be useful, at that time.
823831
824832Builtin function for traversal
825833------------------------------
@@ -828,9 +836,10 @@ There are a number of libraries which provide some kind of object
828836traversal functions. The most popular likely being ``glom `` [#glom ]_.
829837Others include ``jmespath `` [#jmespath ]_ and ``nonesafe `` [#nonesafe ]_.
830838The idea is usually to pass an object and the lookup attributes as
831- string to a function which handles the evaluation.
839+ string to a function which handles the evaluation. It was suggested
840+ to add a ``traverse `` or ``deepget `` function to the stdlib.
832841
833- .. code-block :: python
842+ .. code-block :: python-console
834843
835844 # pip install glom
836845 >>> from glom import glom
@@ -840,8 +849,7 @@ string to a function which handles the evaluation.
840849 >>> glom(data, "a.b.f.g", default=2)
841850 2
842851
843- It was suggested to add a ``traverse `` or ``deepget `` function to the
844- stdlib. While these libraries do work and have its use cases, especially
852+ While these libraries do work and have its use cases, especially
845853``glom `` provides an excellent interface to extract and combine multiple
846854data points from deeply nested objects, they do also have some
847855disadvantages. Passing the lookup attributes as a string means that often
@@ -859,7 +867,9 @@ either an instance of ``Something`` or an instance of ``Nothing``.
859867on ``optional `` attributes.
860868
861869A Python package called ``pymaybe `` [#pymaybe ]_ provides a rough
862- approximation. An example could look like this::
870+ approximation. An example could look like this:
871+
872+ .. code-block :: python-console
863873
864874 # pip install pymaybe
865875 >>> from pymaybe import maybe
@@ -900,8 +910,8 @@ expressions need to be written and evaluated today.
900910
901911An advantages of the ``?. `` and ``?[ ] `` operators is that they do not
902912change the result much aside from adding ``None `` as a possible return
903- of an expression. As such they are a better solution for the use cases
904- outlined in the `Motivation `_ section.
913+ value of an expression. As such they are a better solution for the use
914+ cases outlined in the `Motivation `_ section.
905915
906916No-Value Protocol
907917-----------------
@@ -918,7 +928,7 @@ replaced with ``x.__has_value__()``.
918928There are a few obvious candidates like ``math.nan `` and ``NotImplemented ``.
919929However, while these could be interpreted as representing no value, the
920930interpretation is **domain specific **. For the language itself they *should *
921- be treated as values. For example ``math.nan.imag `` is well defined
931+ still be treated as values. For example ``math.nan.imag `` is well defined
922932(it is ``0.0 ``) and so short-circuiting ``math.nan?.imag `` to return
923933``None `` would be incorrect.
924934
@@ -935,8 +945,8 @@ Though possible, the ``->`` operator is already used in Python for
935945something completely different. Additionally, a majority of other
936946languages which support "``null ``-aware" or "optional chaining"
937947operators use ``?. ``. Some exceptions being Ruby [#ruby ]_ with ``&. ``
938- or PHP [#php ]_ with ``?-> ``. The ``? `` does not have an assigned
939- meaning in Python just yet. As such it makes sense to adopt
948+ or PHP [#php ]_ with ``?-> ``. The ``? `` character does not have an
949+ assigned meaning in Python just yet. As such it makes sense to adopt
940950the most common spelling for the ``None ``-aware access operators.
941951Especially considering that it also works well with the "normal"
942952``. `` and ``[ ] `` operators.
@@ -950,7 +960,7 @@ forward, it was suggested to defer the operator for later.
950960
951961Though it is often helpful to reduce the scope to move forward at all,
952962the ``?[ ] `` operator is necessary to efficiently get items from
953- ``optional `` objects. While for dictionary a suitable alternative is to
963+ ``optional `` objects. While for dictionaries a suitable alternative is to
954964use ``d?.get(key) ``, for general objects developers would have needed
955965to defer to ``o?.__getitem__(key) ``.
956966
@@ -1043,7 +1053,7 @@ Difficult to read
10431053-----------------
10441054
10451055A common objection raised during the discussion was that ``None ``-aware
1046- operators are difficult to read in expressions and add line noise. It
1056+ operators are difficult to read in expressions and add line noise. They
10471057might be too easy to miss besides "normal" attribute access and subscript
10481058operators.
10491059
@@ -1127,7 +1137,7 @@ Some have pointed the `Short-circuiting`_ behavior might be difficult
11271137to understand and suggested to remove it in favor of a simplified
11281138proposal.
11291139
1130- It is true that using short-circuiting that way is new to Python and
1140+ It is true that using short-circuiting that way is uncommon in Python and
11311141as such unknown. That closest analogs would be boolean expressions like
11321142``a or b ``, ``a and b `` which do also short-circuit the expression if
11331143the first value is truthy or falsy respectively. However, while
@@ -1156,8 +1166,8 @@ Just use ...
11561166------------
11571167
11581168A common reply towards the proposal was to use an existing language
1159- concept instead of introducing a syntax. A few alternatives have been
1160- proposed.
1169+ concept instead of introducing a new syntax. A few alternatives have
1170+ been proposed.
11611171
11621172... a conditional expression
11631173****************************
0 commit comments