5 ms·
While not as short as a proper operator .get("key", {}) does work.
by nullwarp 3y ago
While not as short as a proper operator .get("key", {}) does work.
- woolion 3y agoOf course this only works at one level and not arbitrarily deeply, but you still need to check for None with this code; it may actually be better to write `x.get("key") or {}` so that you always get an empty dict. I write 'may' because the difference between None and an empty dict may be very subtle and rarely does the API specify with enough precision what are supposed to be the semantics of each case.
- ddejohn 3y ago> Of course this only works at one level and not arbitrarily deeply It does though, you can chain as many of these as you want: some_dict.get("level_1_key", {}).get("level_2_key", {}).get("level_3_key", {})... edit: >> but you still need to check for None with this code > Not sure what you mean here. You only have to check for None if you use `.get("key")` and don't provide a fallback value. GP was talking about `{"foo": None}` and trying to drill deeper, which I misunderstood. Still, a simple try/except allows you to short-circuit the deeply nested access.
- smilliken 3y agoThe issue is if the dictionary has a key defined and the value is None. Your get expression will return None, causing your next access to raise an error.
- ddejohn 3y agoAh, I see. Still, I'd just catch that exception and move on because it's obvious you won't have anything more deeply nested anyway. Blowing up on `None` is an easy short-circuit.
- kh_hk 3y ago>>> foo = {"foo": None} >>> print(foo.get('foo', {}).get('bar')) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'get' >>> print((foo.get('foo') or {}).get('bar')) None
- ddejohn 3y agoRight, see my other comment: > Blowing up on `None` is an easy short-circuit. The thing being discussed is attempting to access deeply nested values, so short-circuiting here is a win-win. I.e., you wouldn't want to unnecessarily traverse tons of empty dictionaries using the `.get() or {}` trick.
- JimDabell 3y ago> x.get("key") or {} This has the side effect of replacing falsy values like False or 0 with an empty dictionary instead of giving you the actual value. For the exact intended behaviour, you do need to explicitly check for None instead of using a short circuit trick with or.
- ddejohn 3y agoYeah, when trying to drill down into deeply nested structures, it'd be a waste to just blindly nullish-coalesce any None objects into empty dicts instead of just immediately short-circuiting out of the deep access. It's a cute trick but would not pass code review in my shop.
- woolion 3y agoThe problem was underspecified, but I suggested that under the assumption that the value would be an Optional[dict]. If you have another falsy value, it means either Optional[Any] or something like Optional[Union[dict, list]] (I put list as an example, but you get the idea). I would say the only reasonable choice is Optional[dict], in which case it should be sufficient, but Python being Python, it could be anything. And in these cases you need to handle all cases way more carefully.