索引列表类:
class IndexedList(list):
def __init__(self, items, attrs):
super(IndexedList,self).__init__(items)
# do indexing
self._attrs = tuple(attrs)
self._index = {}
_add = self._addindex
for obj in self:
_add(obj)
def _addindex(self, obj):
_idx = self._index
for attr in self._attrs:
_idx[getattr(obj, attr)] = obj
def _delindex(self, obj):
_idx = self._index
for attr in self._attrs:
try:
del _idx[getattr(obj,attr)]
except KeyError:
pass
def __delitem__(self, ind):
try:
obj = list.__getitem__(self, ind)
except (IndexError, TypeError):
obj = self._index[ind]
ind = list.index(self, obj)
self._delindex(obj)
return list.__delitem__(self, ind)
def __delslice__(self, i, j):
for ind in xrange(i,j):
self.__delitem__(ind)
def __getitem__(self, ind):
try:
return self._index[ind]
except KeyError:
return list.__getitem__(self, ind)
def __getslice__(self, i, j):
return IndexedList(list.__getslice__(self, i, j))
def __setitem__(self, ind, new_obj):
try:
obj = list.__getitem__(self, ind)
except (IndexError, TypeError):
obj = self._index[ind]
ind = list.index(self, obj)
self._delindex(obj)
self._addindex(new_obj)
return list.__setitem__(ind, new_obj)
def __setslice__(self, i, j, newItems):
_get = self.__getitem__
_add = self._addindex
_del = self._delindex
newItems = list(newItems)
# remove indexing of items to remove
for ind in xrange(i,j):
_del(_get(ind))
# add new indexing
if isinstance(newList, IndexedList):
self._index.update(newList._index)
else:
for obj in newList:
_add(obj)
# replace items
return list.__setslice__(self, i, j, newList)
def append(self, obj):
self._addindex(obj)
return list.append(self, obj)
def extend(self, newList):
newList = list(newList)
if isinstance(newList, IndexedList):
self._index.update(newList._index)
else:
_add = self._addindex
for obj in newList:
_add(obj)
return list.extend(self, newList)
def insert(self, ind, new_obj):
# ensure that ind is a numeric index
try:
obj = list.__getitem__(self, ind)
except (IndexError, TypeError):
obj = self._index[ind]
ind = list.index(self, obj)
self._addindex(new_obj)
return list.insert(self, ind, new_obj)
def pop(self, ind=-1):
# ensure that ind is a numeric index
try:
obj = list.__getitem__(self, ind)
except (IndexError, TypeError):
obj = self._index[ind]
ind = list.index(self, obj)
self._delindex(obj)
return list.pop(self, ind)
def remove(self, ind_or_obj):
try:
obj = self._index[ind_or_obj]
ind = list.index(self, obj)
except KeyError:
ind = list.index(self, ind_or_obj)
obj = list.__getitem__(self, ind)
self._delindex(obj)
return list.remove(self, ind)
可以用来为:
class Child(object):
def __init__(self, id, name):
self.id = id
self.name = name
class Teacher(object):
def __init__(self, id, name):
self.id = id
self.name = name
class Classroom(object):
def __init__(self, children, teachers):
self.children = IndexedList(children, ('id','name'))
self.teachers = IndexedList(teachers, ('id','name'))
classroom = Classroom([Child('389','pete')], [Teacher('829','bob')])
print classroom.children[0].name # -> pete
classroom.children.append(Child('2344','joe'))
print len(classroom.children) # -> 2
print classroom.children[1].name # -> joe
print classroom.children['joe'].id # -> 2344
print classroom.children['2344'].name # -> joe
p = classroom.children.pop('pete')
print p.name # -> pete
print len(classroom.children) # -> 1
编辑:我曾在一些犯了一个错误的异常处理(捕,而不是KeyError异常IndexError);它是固定的。我将添加一些单元测试代码。如果您遇到任何进一步的错误,请让我知道!
'classroom.childrenBy('Id')['389']'或者类似的东西? – Gabe 2011-03-16 23:13:08
这可以工作,但我仍然必须为每个属性定义一个childrenBy方法,然后我必须通过子列表进行线性搜索以找到匹配的id。我想在列表更改时更新字典。 – jterrace 2011-03-16 23:18:26
当你说“我也可能有几个这些属性”时,我认为你的意思是像'id'这样的几个属性。你的意思是像“小孩”这样的几个属性?如果是这样,你可以有'教室.ById('孩子')['389']'? – Gabe 2011-03-16 23:23:07