4

私がSOで見つけたネストされた辞書の少なくとも2つのまともな実装があります。1つはdefaultdictを使用することであり、もう1つはdictをサブクラス化することです。

どちらの方法も、存在しないキーと値のペアにアクセスするときに副作用があることを除いて、ほとんどの機能で正常に機能します。つまり、そのキーの空のディクショナリを作成し、それを格納して返します。

理想的には、None存在しないキーへのアクセスを試みたときに、エントリ(空の辞書など)を作成せずに戻る実装が必要です。これは実行可能ですか?

psタプルをキーとして使用することでネストされたディクショナリを回避できることは承知していますが、ネストされたディクショナリの各レベルでエントリのコレクションにアクセスする必要があるため、この実装は機能しません。

4

3 に答える 3

2

d[key][subkey] = value欠落しているキーを処理したい場合は、 None を返すという要件を放棄する必要があります。が と同等の場合d[key] is None、これは機能しません。d[key][subkey] = valueNone[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}}}
于 2012-05-28T18:53:10.510 に答える
1

Pythonは、このような状況でのダック タイピングをサポートしています。

>>> d={}
>>> d[1]='Some'
>>> try:
...    att=d[1]
... except KeyError:
...    att=None
... 
>>> print att
Some
>>> try:
...    att=d[1][2][3]
... except KeyError:
...    att=None
... 
>>> print att
None

それをクラスまたは関数にまとめると、あなたが探しているものを簡単にサポートできるはずです。

于 2012-05-28T23:27:45.130 に答える