Perlでは何度も、次のようなことをします。
$myhash{foo}{bar}{baz} = 1
これをPythonにどのように変換しますか?これまでのところ:
if not 'foo' in myhash:
myhash['foo'] = {}
if not 'bar' in myhash['foo']:
myhash['foo']['bar'] = {}
myhash['foo']['bar']['baz'] = 1
もっと良い方法はありますか?
class AutoVivification(dict):
"""Implementation of Perl's autovivification feature."""
def __getitem__(self, item):
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
テスト:
a = AutoVivification()
a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6
print a
出力:
{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
必要なネストの量が固定されている場合、collections.defaultdict
は素晴らしい。
例えば2つの深い入れ子:
myhash = collections.defaultdict(dict)
myhash[1][2] = 3
myhash[1][3] = 13
myhash[2][4] = 9
ネストの別のレベルに移動する場合は、次のようにする必要があります。
myhash = collections.defaultdict(lambda : collections.defaultdict(dict))
myhash[1][2][3] = 4
myhash[1][3][3] = 5
myhash[1][2]['test'] = 6
編集:MizardXは、単純な関数で完全な汎用性を得ることができると指摘しています:
import collections
def makehash():
return collections.defaultdict(makehash)
できるようになりました:
myhash = makehash()
myhash[1][2] = 4
myhash[1][3] = 8
myhash[2][5][8] = 17
# etc
独裁者である必要がある理由はありますか?その特定の構造に説得力のある理由がない場合は、タプルを使用して辞書にインデックスを付けることができます。
mydict = {('foo', 'bar', 'baz'):1} # Initializes dict with a key/value pair
mydict[('foo', 'bar', 'baz')] # Returns 1
mydict[('foo', 'unbar')] = 2 # Sets a value for a new key
タプルキーでdictを初期化する場合は括弧が必要ですが、[]を使用して値を設定または取得する場合は括弧を省略できます。
mydict = {} # Initialized the dict
mydict['foo', 'bar', 'baz'] = 1 # Sets a value
mydict['foo', 'bar', 'baz'] # Returns 1
文字通りの翻訳は次のようになります。
mydict = {'foo' : { 'bar' : { 'baz':1}}}
呼び出し:
>>> mydict['foo']['bar']['baz']
1。
しかし、それは私には少しつまらないように見えます。
(私はPerlの男ではありませんので、あなたのPerlが何をしているのか推測しています)