Как уже упоминалось, словари Python по своей сути неупорядочены. Однако в любой момент времени список их текущих ключей или пар ключей, значений может быть получен с использованием их методов keys()
или items()
.
Потенциальная проблема с использованием этих списков заключается в том, что не только их содержимое, но и порядок, в котором он возвращается, вероятно, будут отличаться, если словарь был изменен (или изменен) с момента последнего использования. Это означает, что вы, как правило, не можете хранить и повторно использовать список, если вы не обновляете его каждый раз, когда словарь изменяется, на случай, если он вам понадобится.
Чтобы сделать этот подход более управляемым, вы можете комбинировать словарь и вспомогательный список в новый производный класс, который выполняет синхронизацию между ними, а также предоставляет метод get_range()
, который использует текущее содержимое списка. Ниже приведен пример кода, показывающего, как это можно сделать. Это основано на идеях, которые я получил от кода в this ActiveState Python Recipe.
class dict_with_get_range(dict):
def __init__(self, *args, **kwrds):
dict.__init__(self, *args, **kwrds)
self._list_ok = False
def _rebuild_list(self):
self._list = []
for k,v in self.iteritems():
self._list.append((k,v))
self._list_ok = True
def get_range(self, begin, end):
if not self._list_ok:
self._rebuild_list()
return dict(self._list[i] for i in range(begin,end+1))
def _wrapMutatorMethod(methodname):
_method = getattr(dict, methodname)
def wrapper(self, *args, **kwrds):
# Reset 'list OK' flag, then delegate to the real mutator method
self._list_ok = False
return _method(self, *args, **kwrds)
setattr(dict_with_get_range, methodname, wrapper)
for methodname in 'delitem setitem'.split():
_wrapMutatorMethod('__%s__' % methodname)
for methodname in 'clear update setdefault pop popitem'.split():
_wrapMutatorMethod(methodname)
del _wrapMutatorMethod # no longer needed
dct = dict_with_get_range({"a":"b", "c":"d", "e":"f"})
print dct.get_range(0, 1)
# {'a': 'b', 'c': 'd'}
del dct["c"]
print dct.get_range(0, 1)
# {'a': 'b', 'e': 'f'}
Основная идея заключается в том, чтобы получить новый класс из dict
, который также имеет внутренний список содержимого для использования нового метода get_range()
он предусматривает, что регулярные словарные объекты нет. Чтобы минимизировать необходимость обновления (или даже создания) этого внутреннего списка, у него также есть флаг, указывающий, обновляется ли этот список или нет, и только проверяет его и перестраивает список, когда это необходимо.
Чтобы сохранить флаг, каждый унаследованный метод словаря, который потенциально изменяет (или мутирует) содержимое словаря, «обернут» вспомогательной функцией, сбрасывает флаг, а затем цепочки к нормальному словарному методу для фактической выполнения операции. Установка их в класс - это просто вопрос о назначении имен методов в одном из двух списков, а затем передача их по одному вспомогательной утилите сразу же после создания класса.
от __indexes__ Вы имеете в виду ключи ??? – mouad
@singularity: глядя на прошлый вопрос OP http://stackoverflow.com/questions/4181367/python-possible-to-filter-dict, вы должны быть правы. – kennytm
НЕТ, не по ключу, сразу после некоторой сортировки (или вообще не сортировки), я хочу, чтобы первая/последняя/средняя части dict ... –