Suppose I want PERL-like autovivication in Python, i.e.:
>>> d = Autovivifier()
>>> d = ['nested']['key']['value']=10
>>> d
{'nested': {'key': {'value': 10}}}
There are a couple of dominant ways to do that:
OK -- easy.
Now suppose I want to return a default value from a dict with a missing key. Once again, few way to do that:
- For a non-nested path, you can use a
__missing__
hook - try/except block wrapping the access to potentially missing key path
- Use
{}.get(key, default)
(does not easily work with a nested dict) i.e., There is no version ofautoviv.get(['nested']['key']['no key of this value'], default)
The two goals seem in irreconcilable conflict (based on me trying to work this out the last couple hours.)
Here is the question:
Suppose I want to have an Autovivifying dict that 1) creates the nested structure for d['arbitrary']['nested']['path']
; AND 2) returns a default value from a non-existing arbitrary nesting without wrapping that in try/except?
Here are the issues:
- The call of
d['nested']['key']['no key of this value']
is equivalent to(d['nested'])['key']['no key of this value']
. Overiding__getitem__
does not work without returning an object that ALSO overrides__getitem__
. - Both the methods for creating an Autovivifier will create a dict entry if you test that path for existence. i.e., I do not want
if d['p1']['sp2']['etc.']
to create that whole path if you just test it with theif
.
How can I provide a dict in Python that will:
- Create an access path of the type
d['p1']['p2'][etc]=val
(Autovivication); - NOT create that same path if you test for existence;
- Return a default value (like
{}.get(key, default)
) without wrapping in try/except - I do not need the FULL set of dict operations. Really only
d=['nested']['key']['value']=val
andd['nested']['key']['no key of this value']
is equal to a default value. I would prefer that testingd['nested']['key']['no key of this value']
does not create it, but would accept that.