回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>我想创建一个多态结构,它可以用最少的输入工作动态创建,并且非常可读。例如:</p>
<pre><code>a.b = 1
a.c.d = 2
a.c.e = 3
a.f.g.a.b.c.d = cucu
a.aaa = bau
</code></pre>
<p>我不想创建中间容器,例如:</p>
^{pr2}$
<p>我的问题与此类似:</p>
<p><a href="https://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python">What is the best way to implement nested dictionaries?</a></p>
<p>但我对那里的解决方案不满意,因为我认为有一个bug:<br/>
即使您不想创建项:假设您想要比较两个多态性结构:它将在第二个结构中创建第一个结构中存在的任何属性,并且只在另一个结构中签入。e、 g组:</p>
<pre><code>a = {1:2, 3: 4}
b = {5:6}
# now compare them:
if b[1] == a[1]
# whoops, we just created b[1] = {} !
</code></pre>
<p>我也想得到最简单的符号</p>
<pre><code>a.b.c.d = 1
# neat
a[b][c][d] = 1
# yuck
</code></pre>
<p>我确实试图从对象类派生。。。但我无法避免留下与上面相同的错误,即仅仅通过读取属性就可以生成属性:一个简单的dir()将尝试创建诸如“<strong>方法</strong>”之类的属性。。。就像在这个例子中,它显然被破坏了:</p>
<pre><code>class KeyList(object):
def __setattr__(self, name, value):
print "__setattr__ Name:", name, "value:", value
object.__setattr__(self, name, value)
def __getattribute__(self, name):
print "__getattribute__ called for:", name
return object.__getattribute__(self, name)
def __getattr__(self, name):
print "__getattr__ Name:", name
try:
ret = object.__getattribute__(self, name)
except AttributeError:
print "__getattr__ not found, creating..."
object.__setattr__(self, name, KeyList())
ret = object.__getattribute__(self, name)
return ret
>>> cucu = KeyList()
>>> dir(cucu)
__getattribute__ called for: __dict__
__getattribute__ called for: __members__
__getattr__ Name: __members__
__getattr__ not found, creating...
__getattribute__ called for: __methods__
__getattr__ Name: __methods__
__getattr__ not found, creating...
__getattribute__ called for: __class__
</code></pre>
<p>谢谢,真的!在</p>
<p>注:到目前为止,我找到的最好的解决方案是:</p>
<pre><code>class KeyList(dict):
def keylset(self, path, value):
attr = self
path_elements = path.split('.')
for i in path_elements[:-1]:
try:
attr = attr[i]
except KeyError:
attr[i] = KeyList()
attr = attr[i]
attr[path_elements[-1]] = value
# test
>>> a = KeyList()
>>> a.keylset("a.b.d.e", "ferfr")
>>> a.keylset("a.b.d", {})
>>> a
{'a': {'b': {'d': {}}}}
# shallow copy
>>> b = copy.copy(a)
>>> b
{'a': {'b': {'d': {}}}}
>>> b.keylset("a.b.d", 3)
>>> b
{'a': {'b': {'d': 3}}}
>>> a
{'a': {'b': {'d': 3}}}
# complete copy
>>> a.keylset("a.b.d", 2)
>>> a
{'a': {'b': {'d': 2}}}
>>> b
{'a': {'b': {'d': 2}}}
>>> b = copy.deepcopy(a)
>>> b.keylset("a.b.d", 4)
>>> b
{'a': {'b': {'d': 4}}}
>>> a
{'a': {'b': {'d': 2}}}
</code></pre>