I would write:
def safe_navigation(obj: Any, *path: str, default: Any = None, strict: bool = False) -> Any:
sentinel = object() if strict else None
for key in path:
obj = obj.get(key, sentinel)
if obj is sentinel:
return default
return obj
The only new disadvantage of this is that it only works on mappings and no longer works on sequences.But I really don't like having this much `Any`; it's generally a sign of poor design.
I wouldn't call a function that mutates the input "safe navigation", personally :)
Er, it doesn't? `.get()` (or `[]` in the original) doesn't change the object, and `obj =` only changes which object the local variable refers to?
This isn't like C++ with its intrusive `=`.
You're right. Python is pass by reference and it's the reference being changed, not the object. This is what happens when you read code on the internet after drinks.
There's certainly humor in a function called "safe navigation" mutating the data structure I'm supposedly safely navigating through :D
I don't think this is correct . The name obj gets rebound, but the dictionary being traversed isn't mutated in any way.
Yeah I agree, no mutation here as far as I can tell
Correct. I was drunk.
Re:What's New in Python 3.12
by wodenokoto on Thursday October 19, 2023 @02:28AM
(#37939237)
I did type it on my phone, so I’m sure it needs a little correction (particularly the choice of exceptions is not optimal, I think) but feel free to run it in any recent python interpreter and return back with any mutation you see.
Re:What's New in Python 3.12
by wodenokoto on Thursday October 19, 2023 @04:35AM
(#37940128)
$ python3
Python 3.11.6 (main, Oct 2 2023, 20:46:14) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import List
>>> def safe_navigation(obj, path: List[str], default=None):
... try:
... for key in path:
... obj = obj[key]
... return obj
... except KeyError:
... return default
...
>>> obj = {1: {1: {1: 2}}}
>>> safe_navigation(obj, [1,1,1])
2
>>> obj
{1: {1: {1: 2}}}
But really, how do you know if your path is missing or the object at the end of the path is None, without using exceptions for communicating this?