<p>这是一个非常有趣和非常实际的情况,曾经可以遇到。
有许多实现,每种实现都能解决某些问题,并且遗漏了一些边缘场景。在</p>
<p>在这些标题中可以找到可能的解决方案和不同的答案。在</p>
^{bq}$
<p>此外,有许多注册官和博客在这一要求'自生',包括维基百科的存在。在</p>
<blockquote>
<p><a href="http://blog.yjl.im/2013/08/autovivification-in-python.html" rel="nofollow noreferrer">http://blog.yjl.im/2013/08/autovivification-in-python.html</a></p>
<p><a href="https://news.ycombinator.com/item?id=3881171" rel="nofollow noreferrer">https://news.ycombinator.com/item?id=3881171</a></p>
<p><a href="https://gist.github.com/hrldcpr/2012250" rel="nofollow noreferrer">https://gist.github.com/hrldcpr/2012250</a></p>
<p><a href="https://en.wikipedia.org/wiki/Autovivification" rel="nofollow noreferrer">https://en.wikipedia.org/wiki/Autovivification</a></p>
<p><a href="http://blogs.fluidinfo.com/terry/2012/05/26/autovivification-in-python-nested-defaultdicts-with-a-specific-final-type/" rel="nofollow noreferrer">http://blogs.fluidinfo.com/terry/2012/05/26/autovivification-in-python-nested-defaultdicts-with-a-specific-final-type/</a></p>
</blockquote>
<p>虽然上面的实现是方便的一旦边缘情况可能仍然有问题。在撰写本文时,还没有一个实现能够很好地处理是否存在原始坐和阻塞嵌套。在</p>
<p>这里有3个主要的方法,这个问题和相关的问题在这里StackOverflow回答。在</p>
<ul>
<li><p>编写一个helper方法,它接受dictionary、value和嵌套键列表
可以很好地处理普通dict对象,但缺少常用的方括号语法,</p></li>
<li><p>使用Defaultdict并编写自定义类,因为Defaultdict为丢失的键提供{},所以基本上这是可行的
语法很棒,但只适用于使用自定义类创建的对象。</p></li>
<li><p>使用元组存储和检索(<a href="https://stackoverflow.com/a/651930/968442">https://stackoverflow.com/a/651930/968442</a>)
最糟糕的想法,甚至不应该被称为解决方案,这里是为什么</p>
<p><code>mydict = {}</code><br/>
<code>mydict['foo', 'bar', 'baz'] = 1</code><br/>
<code>print mydict['foo', 'bar', 'baz']</code></p>
<p>可以正常工作,但是当您访问<code>mydict['foo', 'bar']</code>时,期望值是<code>{'baz':1}</code>,而不是<code>KeyError</code>
这基本上破坏了iterable&nested structure的思想</p></li>
</ul>
<p>在这三种方法中,我打赌选择1。通过编写一个小的辅助方法,可以实际地解决边缘情况,这是我的实现。在</p>
<pre><code>def sattr(d, *attrs):
# Adds "val" to dict in the hierarchy mentioned via *attrs
for attr in attrs[:-2]:
# If such key is not found or the value is primitive supply an empty dict
if d.get(attr) is None or isinstance(d.get(attr), dict):
d[attr] = {}
d = d[attr]
d[attrs[-2]] = attrs[-1]
</code></pre>
<p>现在</p>
^{pr2}$
<p>会产生</p>
<pre><code>{'Rudolf': {'legs': 4, 'animal': 'cat'}}
{'Rudolf': {'legs': {'front-right': {'injured': True}}, 'animal': 'cat'}}
{'Rudolf': {'legs': {'front-left': {'injured': False}, 'front-right': {'injured': True}}, 'animal': 'cat'}}
</code></pre>