I dislike adding another log to a (more than) 10-year old fire, but I'd also check out the dotwiz
library, which I've recently released - just this year actually.
It's a relatively tiny library, which also performs really well for get (access) and set (create) times in benchmarks, at least as compared to other alternatives.
Install dotwiz
via pip
pip install dotwiz
It does everything you want it to do and subclasses dict
, so it operates like a normal dictionary:
from dotwiz import DotWizdw = DotWiz()dw.hello = 'world'dw.hellodw.hello += '!'# dw.hello and dw['hello'] now both return 'world!'dw.val = 5dw.val2 = 'Sam'
On top of that, you can convert it to and from dict
objects:
d = dw.to_dict()dw = DotWiz(d) # automatic conversion in constructor
This means that if something you want to access is already in dict
form, you can turn it into a DotWiz
for easy access:
import jsonjson_dict = json.loads(text)data = DotWiz(json_dict)print data.location.city
Finally, something exciting I am working on is an existing feature request so that it automatically creates new child DotWiz
instances so you can do things like this:
dw = DotWiz()dw['people.steve.age'] = 31dw# ✫(people=✫(steve=✫(age=31)))
Comparison with dotmap
I've added a quick and dirty performance comparison with dotmap
below.
First, install both libraries with pip
:
pip install dotwiz dotmap
I came up with the following code for benchmark purposes:
from timeit import timeitfrom dotwiz import DotWizfrom dotmap import DotMapd = {'hey': {'so': [{'this': {'is': {'pretty': {'cool': True}}}}]}}dw = DotWiz(d)# ✫(hey=✫(so=[✫(this=✫(is=✫(pretty={'cool'})))]))dm = DotMap(d)# DotMap(hey=DotMap(so=[DotMap(this=DotMap(is=DotMap(pretty={'cool'})))]))assert dw.hey.so[0].this['is'].pretty.cool == dm.hey.so[0].this['is'].pretty.cooln = 100_000print('dotwiz (create): ', round(timeit('DotWiz(d)', number=n, globals=globals()), 3))print('dotmap (create): ', round(timeit('DotMap(d)', number=n, globals=globals()), 3))print('dotwiz (get): ', round(timeit("dw.hey.so[0].this['is'].pretty.cool", number=n, globals=globals()), 3))print('dotmap (get): ', round(timeit("dm.hey.so[0].this['is'].pretty.cool", number=n, globals=globals()), 3))
Results, on my M1 Mac, running Python 3.10:
dotwiz (create): 0.189dotmap (create): 1.085dotwiz (get): 0.014dotmap (get): 0.335