{"id":522,"date":"2018-02-27T01:00:52","date_gmt":"2018-02-26T17:00:52","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=522"},"modified":"2026-02-18T01:20:35","modified_gmt":"2026-02-17T17:20:35","slug":"dot-notation-obj-x-y-z-for-nested-objects-and-dictionaries-in-python","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/dot-notation-obj-x-y-z-for-nested-objects-and-dictionaries-in-python.html","title":{"rendered":"Dot notation (obj.x.y.z) for nested objects and dictionaries in Python"},"content":{"rendered":"<p>Simple implementations of <code>nested_getattr(obj, attr, default)<\/code>, <code>nested_setattr(obj, attr, val)<\/code> and <code>nested_dict_get(dictionary, dotted_key)<\/code>.<\/p>\n<h2>Nested Object<\/h2>\n<pre class=\"line-numbers\"><code class=\"language-py\">import functools\n\nraise_attribute_error = object()\ndef nested_getattr(obj, attr, default=raise_attribute_error):\n    try:\n        return functools.reduce(getattr, attr.split('.'), obj)\n    except AttributeError:\n        if default != raise_attribute_error:\n            return default\n        raise\n\n# only support setting an attribute on an existed nested attribute\ndef nested_setattr(obj, attr, val):\n    pre, _, post = attr.rpartition('.')\n    return setattr(nested_getattr(obj, pre) if pre else obj, post, val)\n\nnested_getattr(user, 'settings.enable_nsfw', None)\n\nnested_setattr(user, 'settings.enable_nsfw', True)  # work\nnested_setattr(user, 'nonexistent_field.whatever_field', True)  # raise AttributeError<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/11975781\/why-does-getattr-not-support-consecutive-attribute-retrievals\">https:\/\/stackoverflow.com\/questions\/11975781\/why-does-getattr-not-support-consecutive-attribute-retrievals<\/a><br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/31174295\/getattr-and-setattr-on-nested-objects\">https:\/\/stackoverflow.com\/questions\/31174295\/getattr-and-setattr-on-nested-objects<\/a><\/p>\n<h2>Nested Dictionary<\/h2>\n<pre class=\"line-numbers\"><code class=\"language-py\">import functools\n\ndef nested_dict_get(dictionary, dotted_key):\n    keys = dotted_key.split('.')\n    return functools.reduce(lambda d, key: d.get(key) if d else None, keys, dictionary)\n\nuser_dict = {\n    'id': 123,\n    'username': 'vinta',\n    'settings': {\n        'enable_nsfw': True,\n    },\n}\n\nnested_dict_get(user_dict, 'username')  # return 'vinta'\nnested_dict_get(user_dict, 'settings.enable_nsfw')  # return True\nnested_dict_get(user_dict, 'settings.notification.new_follower')  # return None<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/stackoverflow.com\/questions\/25833613\/python-safe-method-to-get-value-of-nested-dictionary\">https:\/\/stackoverflow.com\/questions\/25833613\/python-safe-method-to-get-value-of-nested-dictionary<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Simple implementations of nested_getattr(obj, attr, default), nested_setattr(obj, attr, val) and nested_dict_get(dictionary, dotted_key).<\/p>\n","protected":false},"author":1,"featured_media":523,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[2],"class_list":["post-522","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-about-python","tag-python"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/522","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=522"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/522\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/523"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=522"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=522"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=522"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}