[Python-ideas] Bring line continuation to multi-level dictionary lookup

Akira Li 4kir4.1i at gmail.com
Thu Sep 17 06:16:02 CEST 2015


John Wong <gokoproject at gmail.com> writes:

> Hi everyone.
>
> I work with APIs which have deep nested dictionary structure response.
> Imagine a simplified case:
>
> foo = {1: {2: {3: {4: {5: 6 } } } }
>
> Now imagine I need to get to 6:
>
> foo['1']['2']['3']['4']['5']['6']
>
> This looks managable, but if the key name is long, then I certainly will
> end doing this to respect my style guide. To make it concrete, let's use
> something reallistic, a response call from AWS API:
>
> response = {'DescribeDBSnapshotsResponse': {'ResponseMetadata':
> {'RequestId': '123456'}, 'DescribeDBSnapshotsResult': {'Marker': None,
> 'DBSnapshots': [{'Engine': 'postgres'}]}}}
>
> If I had to get to the Engine I'd do this:
>
> detail_response = response["DescribeDBSnapshotsResponse"]
> result = detail_response["DescribeDBSnapshotsResult"]
>
> This is only a few level deep, but imagine something slightly longer (I
> strict out so much from this response). Obviously I am picking some real
> example but key name being really long to sell my request.
>
> Can we do it differently? How about
> print(response.get(
>     "DescribeDBSnapshotsResponse").get(
>     "DescribeDBSnapshotsResult").get(
>     "DBSnapshots")[0].get(
>     "Engine"))
>
> Okay. Not bad, almost like writing in Javascript except Python doesn't
> allow you to do line continuation before the got at all, so you are stuck
> with (.
>
> But the problem with the alternative is that
> if DescribeDBSnapshotsResult is a non-existent key, you will just get None,
> because that's the beauty of the .get method for a dictionary object. So
> while this allows you to write in slightly different way, I am costing
> silent KeyError exception. I wouldn't know which key raised the exception.
> Whereas with [key1][key2] I know if key1 doesn't exist, the exception will
> explain to me that key1 does not exist.

  import functools
  import operator
  
  functools.reduce(operator.getitem, [
      "DescribeDBSnapshotsResponse",
      "DescribeDBSnapshotsResult",
      "DBSnapshots",
      0,
      "Engine"], response)
  

> So here I am, thinking, what if we can do this?
>
> response(
>     ["DescribeDBSnapshotsResponse"]
>     ["DescribeDBSnapshotsResult"]
> )
>
> You get the point. This looks kinda ugly, but it doesn't require so many
> assignment. I think this is doable, after all [ ] is still a method call
> with the key name passed in. I am not familar with grammar, so I don't know
> how hard and how much the implementation has to change to adopt this.
>
> Let me know if this is a +1 or -10000000 bad crazy idea.
>
> Thanks.
>
> John



More information about the Python-ideas mailing list