Поскольку мы не знаем заранее, нужен ли нам словарь или список, то вы не можете комбинировать автовивификацию со списками. Если, отработав ответ Носкло на связанный вопрос, вы добавите список «функций» в базовый словарь. В основном предполагая порядок «сортировки» для ключей, и всегда используя его с методами списка. Я сделал это в качестве примера:
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
Это следует за основной функцией автовивификации динамического генерирования себя для ключей dud. Тем не менее, он также реализует некоторые из методов , перечисленных здесь . Это позволяет ему действовать как квази-список / диктат.
Для остальных функций списка добавьте перечисленные методы. Я рассматриваю это как словарь с методами списка. Если вызывается метод списка, он делает предположение о порядке хранения элементов, а именно о том, что строки сортируются ниже целых чисел, а ключи всегда в «отсортированном» порядке.
Также поддерживается добавление в качестве примера этих методов . Это происходит из моего собственного варианта использования. Мне нужно было добавить элементы из словаря AutoVivified, но если он не существует, создается и возвращается новый объект AutoVivification
. У них нет целочисленного значения, поэтому вы не можете сделать это:
rp = AutoVivification()
rp['a']['b'] = 3
rp['a']['b'] + rp['q']
Это побеждает цель, так как я не знаю, будет ли там какая-то вещь, но я все равно хочу дефолт. Поэтому я добавил к нему методы __add__
и __radd__
. Они используют length
нижележащего словаря в качестве значения integer
, поэтому для вновь созданного AV-объекта добавляется нулевое значение. Если в ключе есть что-то, кроме объекта AV, то мы получим метод сложения, если он реализован.