
On Tue, 11 Jul 2023 at 08:05, Jothir Adithyan <adithyanjothir@gmail.com> wrote:
Assumptions:
The problem statement is based on a few assumptions: - You prefer chaining `get` statements for cleaner code. - You expect at least some of the `get` methods to return `None`. - You want to avoid the hassle of using `try` and `except` for every `get` chain.
The main assumption here is that None is a perfectly valid value in your data, and should be equivalent to the key being omitted. I think this is uncommon enough to be better done with custom code. But fortunately, there's a really cool way to write that custom code, and that's a path lookup - this is a sort of function that I've written in a lot of these situations. Using your examples:
import contextlib parent_dict = PlayDict() parent_dict['k1'] = None parent_dict['k2'] = {"child_key": "val"} # Parent dict can contain nested dicts
with contextlib.suppress(AttributeError): result = parent_dict.get("k1", {}).get("child_key") # This will raise AttributeError
result = parent_dict.get_or("k1", default={}, arbitrary={}).get("child_key") # This will work
I'd write it like this: def lookup(basis, *keys, default=None): for key in keys: basis = basis.get(key) if basis is None: return default return basis result = lookup(parent_dict, "k1", "child_key") This quite tidily expresses the intent ("delve into this dictionary and follow this path, returning None if there's nothing there"), and is compact, with no repetition. It's a relatively short helper function too, and easy to change into other forms. For example, here's another version that I use, which guarantees to always return a dictionary: def lookup(basis, *keys): for key in keys: if key not in basis: basis[key] = {} basis = basis[key] return basis Etcetera. Flexible and very handy. ChrisA