辞書が必要なのかリストが必要なのかが事前にわからないため、自動有効化をリストと組み合わせることはできません。リンクされた質問からのNoskloの回答に基づいて作業しない限り、リストの「機能」を基礎となる辞書に追加します。基本的に、キーの「ソート」順序を想定し、常にリスト メソッドで使用します。例としてこれを行いました:
class AutoVivification(dict):
"""Implementation of perl's autovivification feature. Has features from both dicts and lists,
dynamically generates new subitems as needed, and allows for working (somewhat) as a basic type.
"""
def __getitem__(self, item):
if isinstance(item, slice):
d = AutoVivification()
items = sorted(self.iteritems(), reverse=True)
k,v = items.pop(0)
while 1:
if (item.start < k < item.stop):
d[k] = v
elif k > item.stop:
break
if item.step:
for x in range(item.step):
k,v = items.pop(0)
else:
k,v = items.pop(0)
return d
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
def __add__(self, other):
"""If attempting addition, use our length as the 'value'."""
return len(self) + other
def __radd__(self, other):
"""If the other type does not support addition with us, this addition method will be tried."""
return len(self) + other
def append(self, item):
"""Add the item to the dict, giving it a higher integer key than any currently in use."""
largestKey = sorted(self.keys())[-1]
if isinstance(largestKey, str):
self.__setitem__(0, item)
elif isinstance(largestKey, int):
self.__setitem__(largestKey+1, item)
def count(self, item):
"""Count the number of keys with the specified item."""
return sum([1 for x in self.items() if x == item])
def __eq__(self, other):
"""od.__eq__(y) <==> od==y. Comparison to another AV is order-sensitive
while comparison to a regular mapping is order-insensitive. """
if isinstance(other, AutoVivification):
return len(self)==len(other) and self.items() == other.items()
return dict.__eq__(self, other)
def __ne__(self, other):
"""od.__ne__(y) <==> od!=y"""
return not self == other
これは、ダッドキーに対して動的に生成する基本的な自動有効化機能に従います。ただし、ここにリストされているメソッドの一部も実装しています。これにより、準リスト/辞書のように振る舞うことができます。
リストの残りの機能については、リストされているメソッドを追加してください。リストメソッドを使用して辞書として扱っています。list メソッドが呼び出されると、保持されている項目の順序について、つまり、文字列は整数より下位にソートされ、キーは常に「ソートされた」順序であると仮定されます。
これらのメソッドの例として、追加もサポートしています。これは私自身のユースケースから来ています。AutoVivified ディクショナリからアイテムを追加する必要がありましたが、存在しない場合は、新しいAutoVivification
オブジェクトが作成されて返されます。それらには整数の「値」がないため、これを行うことはできません:
rp = AutoVivification()
rp['a']['b'] = 3
rp['a']['b'] + rp['q']
何かがそこにあるかどうかわからないので、それは目的に反しますが、とにかくデフォルトが必要です。__add__
そのため、 and__radd__
メソッドを追加しました。length
基礎となるディクショナリの を値として使用するinteger
ため、新しく作成された AV オブジェクトの値は追加のためにゼロになります。キーに AV オブジェクト以外の何かが含まれている場合、実装されている場合はその追加メソッドを取得します。