Defaultdictをdefaultdictのデフォルトにもする方法はありますか? (つまり、無限レベルの再帰的なdefaultdict?)
私ができるようにしたい:
_x = defaultdict(...stuff...)
x[0][1][0]
{}
_
したがって、x = defaultdict(defaultdict)
を実行できますが、それは第2レベルにすぎません。
_x[0]
{}
x[0][0]
KeyError: 0
_
これを行うことができるレシピがあります。しかし、通常のdefaultdict引数を使用するだけで実行できますか?
これは、無限レベルの再帰的なdefaultdictの実行方法を尋ねているため、Python:defaultdictのdefaultdict?とは異なります。これは、2レベルのdefaultdictを実行する方法でした。
おそらくbunchパターンを使用することになりますが、これを行う方法がわからないことに気付いたとき、興味を持ちました。
任意の数のレベルの場合:
def rec_dd():
return defaultdict(rec_dd)
>>> x = rec_dd()
>>> x['a']['b']['c']['d']
defaultdict(<function rec_dd at 0x7f0dcef81500>, {})
>>> print json.dumps(x)
{"a": {"b": {"c": {"d": {}}}}}
もちろん、ラムダを使用してこれを行うこともできますが、ラムダは読みにくいと思います。いずれにしても、次のようになります。
rec_dd = lambda: defaultdict(rec_dd)
ここでの他の回答は、「無限に多く」のdefaultdict
を含むdefaultdict
を作成する方法を示していますが、2つだけを持っていることが最初のニーズだったと思うものに対処できません-depth defaultdict。
あなたが探しているかもしれません:
_defaultdict(lambda: defaultdict(dict))
_
この構成を好む理由は次のとおりです。
defaultdict
の「リーフ」を辞書以外のものにすることができます。例:defaultdict(lambda: defaultdict(list))
またはdefaultdict(lambda: defaultdict(set))
それを行うための気の利いたトリックがあります:
_tree = lambda: defaultdict(tree)
_
その後、x = tree()
でx
を作成できます。
BrenBarnのソリューションに似ていますが、変数tree
の名前が2回含まれていないため、変数辞書を変更した後でも機能します。
_tree = (lambda f: f(f))(lambda a: (lambda: defaultdict(a(a))))
_
その後、x = tree()
を使用して新しいx
をそれぞれ作成できます。
def
バージョンでは、関数閉鎖スコープを使用して、tree
名が再バインドされた場合に既存のインスタンスが動作を停止するという欠陥からデータ構造を保護できます。次のようになります。
_from collections import defaultdict
def tree():
def the_tree():
return defaultdict(the_tree)
return the_tree()
_
また、適切にフォーマットされたrepr
と同様に、無限のネストをサポートする、よりOOPスタイルの実装を提案します。
class NestedDefaultDict(defaultdict):
def __init__(self, *args, **kwargs):
super(NestedDefaultDict, self).__init__(NestedDefaultDict, *args, **kwargs)
def __repr__(self):
return repr(dict(self))
使用法:
my_dict = NestedDefaultDict()
my_dict['a']['b'] = 1
my_dict['a']['c']['d'] = 2
my_dict['b']
print(my_dict) # {'a': {'b': 1, 'c': {'d': 2}}, 'b': {}}