正如其他人所提到的,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() 方法使用,它提供了常规字典对象没有的方法。为了尽量减少更新(甚至创建)这个内部列表的需要,它还有一个标志来指示列表是否是最新的,并且只在必要时检查它并重建列表。
为了维护标志,每个可能更改(或变异)字典内容的继承字典方法都使用帮助函数“包装”,重置标志,然后链接到普通字典方法以实际执行操作。将它们安装到类中只需将方法的名称放在两个列表之一中,然后在创建类后立即将它们一次传递给辅助实用程序。