I want to do this:
foo23 = base["foo23"]["subfoo"]["subsubfoo"]
print(foo23)
[2,3]
foo23 = base["noexist"]["nothereeither"]["nope"]
print(foo23)
None
I can't seem to accomplish this, using defaultdict and specialized dictionaries. The failed access of the first call can return a 'None', but then the following fields cause an exception for it not being subscriptable. Just wondering if this is possible.
If you wanted to walk a tree by a list of keys where the tree might have nodes that where dictionaries or lists or values then you might do:
def find_value_by_keys(root, list_of_keys):
for key in list_of_keys:
try:
root = root[key]
except KeyError:
return None
return root
root = {
"foo": {"bar": "baz"},
"foo2": ["bar", "baz"]
}
print(find_value_by_keys(root, ["foo", "bar"]))
print(find_value_by_keys(root, ["foo2", 1]))
print(find_value_by_keys(root, ["foo", "noexist"]))
print(find_value_by_keys(root, ["foo", 2]))
That will give you:
baz
baz
None
None
while failing fast and without resorting to a casting your tree to a default dict.
If you wanted to support a list of keys that was a dot separated sting you might be able to do that if you guarded for only passing integer indexes to lists. Perhaps something like:
def find_value_by_keys(root, list_of_keys):
if isinstance(list_of_keys, str):
list_of_keys = list_of_keys.split(".")
for key in list_of_keys:
try:
root = root[int(key) if isinstance(root, list) else key]
except (ValueError, KeyError):
return None
return root
root = {
"foo": {"bar": "baz"},
"foo2": ["bar", "baz"]
}
print(find_value_by_keys(root, ["foo", "bar"]))
print(find_value_by_keys(root, "foo.bar"))
print(find_value_by_keys(root, ["foo2", 1]))
print(find_value_by_keys(root, "foo2.1"))
print(find_value_by_keys(root, "foo2.x"))
print(find_value_by_keys(root, ["foo", "noexist"]))
print(find_value_by_keys(root, "foo.noexist"))
print(find_value_by_keys(root, ["foo", 2]))
print(find_value_by_keys(root, "foo.2"))