Data point: I find all the examples in PEP 505 less readable using the proposed new operators.
Trying to explain why: The syntax feels *too* compact (Perl-like?) - when reading it, every time you see a None-aware operator (*if* you notice it), you have to jerk to a halt and say, "Whoa!  What's going on here?".
I have some sympathy with this use case of exploring a nested-dict (JSON derived?) structure, but this can be written as

try:
    config.get("handler").get("parameters").get("y")
except Attribute Error:
    # Handle missing value.

or something similar (I haven't tested it).  Even using the new operators, in a realistic case you would probably have to test if the result is None and take different action accordingly.
Best wishes
Rob Cliffe

On 18/10/2021 19:26, Guido van Rossum wrote:
On Mon, Oct 18, 2021 at 9:35 AM Paul Bryan <pbryan@anode.ca> wrote:
NoneType is just another type, and in type checking scenarios should be expressed with `Optional[type]` or more preferably in the future `type | None`; `None` is not a non-value. Assuming what I just wrote is true, I don't get what the basis of this thread is; what am I missing?

To me the thread isn't about type checking. It is about APIs that are built into the language that special-case None, in particular dict.get(). In certain cases, encountered commonly in certain styles of coding (data science? web programming?), users encounter data that is structured as dicts nested multiple levels. This is often out of the user's control, as the dict is returned by reading a JSON value whose structure is controlled by some other framework (often not specific to Python).

For example, if we have a config structure like this:

config = {
  "timeout": 0.1,
  "handler: {
    "timeout-override": 0.4,
    "method-name": "plot",
    "parameters": {
      "x": 10,
      "y": "auto",
    }
  }
}

where the convention is that keys at any level may be omitted altogether and config itself may be NOne, then to safely access the value of config["handler"]["parameters"]["y"] we would have to write

y = None  # Default
if config is not None:
  handler = config.get("handler")
  if handler is not None:
    parameters = handler.get("parameters")
    if parameters is not None:
      y = parameters.get("y")

This kind of pattern (and all the various other ways of writing it, e.g. using the walrus or passing {} as the second argument to dict.get()) can be *very* common if that's the kind of data you're given and that's the kind of app you have to write, and you can't control the format of the data.

Using ?. this can be written as

y = config?.get("handler")?.get("parameters")?.get("y")

More examples are in PEP 505 itself, see https://www.python.org/dev/peps/pep-0505/#examples

--
--Guido van Rossum (python.org/~guido)

_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/GKOYEMS7RFHTRPDJ23RAHBBNTFDXKGFJ/
Code of Conduct: http://python.org/psf/codeofconduct/