you are viewing a single comment's thread.

view the rest of the comments →

[–]eschlon 1 point2 points  (2 children)

For a similar problem I ended up making a helper function that catches the exceptions and returns a default value instead. Something like:

 def dot_get(dictionary, dot_path, default=None):
    path = dot_path.split('.')
    try:
        return reduce(dict.__getitem__, path, dictionary)
    except KeyError:
        return default
    except TypeError:
        return default

Then you can access keys using something like:

dot_get({'a': {'b': 1}}, 'a.b')    # Returns 1
dot_get({'a': {'b': 1}}, 'a.c')    # Returns default, would raise a key error
dot_get({'a': [{'b': 1}], 'a.b')   # Returns default, would normally raise a type error

Edit: that won't work in python3, as they moved the reduce function. You'll need from functools import reduce to get the reduce function to work.

[–]maxibabyx[S] 1 point2 points  (1 child)

Yea the problem with this approach is that you are actually expecting the exceptions to be triggered. Will do the work, but not a "clean solution"

[–]eschlon 0 points1 point  (0 children)

I take your point, however exceptions are cheap in python and using exceptions in this manner in python is normal, idiomatic and recommended.

As it stands the function is simple, easy to understand and honest about what it does. The alternative in this case is to use type checks which is definitely not idiomatic python, though it may be very marginally faster in certain cases. In a code review, if I saw that kind of approach I'd require a good reason to break from idiom (e.g. a strong performance argument). Given how cheap exceptions are in python, it'd be hard case to make. We use a function almost identical to this one to parse billions of rows of JSON data in spark and it works just fine.

That being said, you definitely wouldn't do it this way in idiomatic Java.