dict.get_deep()

Peter J. Holzer hjp-python at hjp.at
Sun Apr 3 15:45:12 EDT 2022


On 2022-04-03 17:58:09 +0300, Kirill Ratkin via Python-list wrote:
> 02.04.2022 23:44, Marco Sulla пишет:
> > A proposal. Very often dict are used as a deeply nested carrier of
> > data, usually decoded from JSON. Sometimes I needed to get some of
> > this data, something like this:
> > 
> > data["users"][0]["address"]["street"]
> > 
> > What about something like this instead?
> > 
> > data.get_deep("users", 0, "address", "street")

Yup. I need something like this quite frequently, so I wrote a little
utility function (which I copy and paste into lots of code - I probably
should package that up, but a package with a single short function feels
weird).

[...]
> > data.get_deep("users", 0, "address", "street", default="second star")

Yep. Did that, too. Plus pass the final result through a function before
returning it.

I'm not sure whether I considered this when I wrote it, but a function
has the advantage of working with every class which can be indexed. A
method must be implemented on any class (so at least dict and list to be
useful).


> Recently I met same issue. A service I intergated with was documented badly
> and sent ... unpredictable jsons.
> 
> And pattern matching helped me in first solution. (later I switched to
> Pydantic models)
> 
> For your example I'd make match rule for key path you need. For example:
> 
> 
> data = {"users": [{"address": {"street": "Baker"}}]}
> 
> match data:
>     case {"users": [{"address": {"street": street}}]}:
>         print(f"street: {street}")
> 
>     case _:
>         print("unsupported message structure")

Neat. But that's 5 lines instead of one. I simple loop around try/except
also takes 5 lines, and the latter can be easily moved into a function,
like this:

def get_nested(coll, path, default=None, cast=None):
    for i in path:
        try:
            coll = coll[i]
        except (KeyError, IndexError, TypeError):
            return default
    if cast:
        coll = cast(coll)
    return coll

which can then be called in a single line.

> Structural matching gives you warranty you process exactly message you
> expect and explicitly discards messages with another structure.

True, and sometimes useful, I'm sure. Not sure whether it would have
helped me in the cases where I used the utility function above.

        hp

-- 
   _  | Peter J. Holzer    | Story must make more sense than reality.
|_|_) |                    |
| |   | hjp at hjp.at         |    -- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |       challenge!"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://mail.python.org/pipermail/python-list/attachments/20220403/951e11b7/attachment.sig>


More information about the Python-list mailing list