d[key][subkey] = value
欠落しているキーを処理したい場合は、 None を返すという要件を放棄する必要があります。が と同等の場合d[key] is None
、これは機能しません。d[key][subkey] = value
None[subkey] = value
欠損値に対してできることは、まだキーに割り当てずに空の dict のようなオブジェクトを返すことです。そのオブジェクトが親への参照を保持している場合、階層の下に明示的な割り当てがあるまで、割り当てを遅らせることができます。
実装例 (これは不完全です。完全に機能する dict サブクラスを作成するには、setitem をオーバーライドする以上のことを行う必要があります):
class NestedDict(dict):
def __init__(self, parent=None, parentkey=None):
self.parent = parent
self.parentkey = parentkey
def __missing__(self, key):
return NestedDict(self, key)
def __setitem__(self, key, value):
if self.parent is not None:
self.parent[self.parentkey] = self
self.parent = None
super(NestedDict, self).__setitem__(key, value)
>>> d = NestedDict()
>>> d[1][2][3] = 4
>>> d[2]
{}
>>> d.keys()
[1]
>>> d[1][2][3]
4
別のアプローチは、キーがタプルの場合、オーバーライド__getitem__
し__setitem__
てネストされたルックアップを実行することです。__getitem__
このバージョンでは、通常の dict との一貫性を保つために、不足しているキーに対してKeyError が返されます。必要に応じて、代わりに None を返すように簡単に変更できます。
class NestedDict(dict):
def __getitem__(self, key):
if isinstance(key, tuple):
try:
x = self
for k in key:
x = x[k]
return x
except (KeyError, TypeError):
raise KeyError(key)
else:
return super(NestedDict, self).__getitem__(key)
def __setitem__(self, key, value):
if isinstance(key, tuple):
d = self
for k in key[:-1]:
d = d.setdefault(k, NestedDict())
d[key[-1]] = value
else:
super(NestedDict, self).__setitem__(key, value)
>>> d = NestedDict()
>>> d[1,2,3] = 4
>>> d[1,2,3]
4
>>> d[1,2,4]
KeyError: (1, 2, 4)
>>> d
{1: {2: {3: 4}}}