Storing dictionary path in Python
Depending on what you need, the easiest option may be to use tuples as dictionary keys instead of nested dictionaries:
kidshair['allkids', 'child3', 'hair']
mypath = ('allkids', 'child3', 'hair')
kidshair[mypath]
The only issue with this is that you can't get a portion of the dictionary, so, for example, you can't (easily/efficiently) access everything to do with 'child3'
. This may or may not be an appropriate solution for you depending on your usage.
An alternative with your current structure is to do something like this:
>>> from functools import partial
>>> test = {"a": {"b": {"c": 1}}}
>>> def itemsetter(item):
... def f(name, value):
... item[name] = value
... return f
...
>>> mypath = partial(itemsetter(test["a"]["b"]), "c")
>>> mypath(2)
>>> test
{'a': {'b': {'c': 2}}}
Here we make a function itemsetter()
, which (in the vein of operator.itemgetter()
) gives us a function that that sets the relevant key in the given dictionary. We then use functools.partial
to generate a version of this function with the key we want pre-filled. It's not quite mypath = blue
either, but it's not bad.
If you don't want to bother with making something consistent to the operator
module, you could simply do:
def dictsetter(item, name):
def f(value):
item[name] = value
return f
mypath = dictsetter(test["a"]["b"], "c")
mypath(2)
You could create a set of functions that accesses a 'path' for a given dictionary:
def pathGet(dictionary, path):
for item in path.split("/"):
dictionary = dictionary[item]
return dictionary
def pathSet(dictionary, path, setItem):
path = path.split("/")
key = path[-1]
dictionary = pathGet(dictionary, "/".join(path[:-1]))
dictionary[key] = setItem
Usage:
>>> pathGet(kidshair, "allkids/child1/hair")
'blonde'
>>> pathSet(kidshair, "allkids/child1/hair", "blue")
>>> kidshair['allkids']['child1']
{'hair': 'blue'}