我需要一个类似列表的对象,只要访问大于或等于其长度的插槽号就会“自动增长”,用一些预先指定的默认值填充所有新创建的插槽。 E.g:
# hypothetical DefaultList class
x = DefaultList(list('abc'), default='*')
x[6] = 'g'
print x[2], x[4], x[6], x[8] # should print 'c * g *'
谢谢!
PS。我知道实现这样的课程并不困难,但我尽可能避免轮胎改造,特别是如果一个特别有效/精心设计的轮子已经存在。
PS2。 dict(或collections.defaultdict)不是所需数据结构的可接受实现。为什么,请看这里:http://groups.google.com/group/comp.lang.python/msg/bcf360dfe8e868d1?hl=en
答案 0 :(得分:3)
class DefaultList(list):
def __init__(self,*args,**kwargs):
list.__init__(self,*args)
self.default=kwargs.get('default',None)
def __getitem__(self,key):
# retrieving an item does not expand the list
if isinstance(key,slice):
return [self[elt] for elt in range(key.start,key.stop,key.step)]
else:
try:
return list.__getitem__(self,key)
except IndexError:
return self.default
def __setitem__(self,key,value):
# setting an item may expand the list
try:
list.__setitem__(self,key,value)
except IndexError:
self.extend([self.default]*(key-len(self)))
self.append(value)
x = DefaultList(list('abc'), default='*')
print(x)
# ['a', 'b', 'c']
x[6] = 'g'
print(x)
# ['a', 'b', 'c', '*', '*', '*', 'g']
print x[2], x[4], x[6], x[8] # should print 'c * g *'
# c * g *
print(x[2:9:2])
# ['c', '*', 'g', '*']
答案 1 :(得分:1)
我会使用sparse数据结构(1xn矩阵)。
答案 2 :(得分:1)
你总是可以创建一个处理这个问题的函数:
def fillList(item, slot, myList):
length = len(myList)
if slot > length:
augmentation = [item for x in range(slot-length)]
myList.extend(augmentation)
else:
myList[slot] = item
虽然不是数据结构,但确实能达到你想要的效果。
答案 3 :(得分:0)
使用wheaties解决方案的想法并制作更漂亮的界面:
您可以从列表继承并覆盖列表' getitem (索引)'方法,该方法映射到您的类中的[index]。它应该是这样的:
class GrowingList(list):
def __getitem__(self, index):
length = len(self)
# list is 0 indexed
if index >= length:
tail = [ self.default_value for x in range(index - length + 1)]
self.extend(tail)
return super(self.__class__, self).__getitem__(index)
如果不扩展列表,可以使用相同的代码,但只返回无效索引的默认值
这保留了整个列表界面。
答案 4 :(得分:0)
(这不是一个新的答案;只是对unutbu的评论。应该可以在评论中发布这样的内容;它不是,所以我必须将其作为答案发布。)
CombineListClasses
和CombineListClasses2
继承自两个都继承自list
的类。行为和doctests很简单,但在原始版本中严重破坏。
这是Python数据模型中的所有标准做法;你几乎不应该直接调用基类方法,而不是通过super
。
class DefaultList(list):
"""
>>> x = DefaultList('abc', default='*')
>>> x
['a', 'b', 'c']
>>> x[6] = 'g'
>>> x
['a', 'b', 'c', '*', '*', '*', 'g']
>>> x[2], x[4], x[6], x[8] # should print 'c * g *'
('c', '*', 'g', '*')
>>> x[2:9:2]
['c', '*', 'g', '*']
>>> x = DefaultList()
>>> x[1] = 'a'
>>> x
[None, 'a']
>>> x = DefaultList(sequence=[1,2,3], default=5)
>>> x
[1, 2, 3]
>>> x[10]
5
"""
def __init__(self, *args, **kwargs):
if 'default' in kwargs:
self.default = kwargs['default']
del kwargs['default']
else:
self.default = None
super(DefaultList, self).__init__(*args, **kwargs)
def __getitem__(self, key):
# retrieving an item does not expand the list
if isinstance(key, slice):
return [self[elt] for elt in range(key.start, key.stop, key.step)]
else:
try:
return super(DefaultList, self).__getitem__(key)
except IndexError:
return self.default
def __setitem__(self, key, value):
# setting an item may expand the list
try:
super(DefaultList, self).__setitem__(key, value)
except IndexError:
self.extend([self.default]*(key-len(self)))
self.append(value)
# Another class that derives from list:
class AddMethodToList(list):
def __init__(self, *args, **kwargs):
self.value = kwargs['value']
del kwargs['value']
super(AddMethodToList, self).__init__(*args, **kwargs)
def new_method(self):
return self.value
# Derive from both classes.
class CombineListClasses(AddMethodToList, DefaultList):
"""
>>> a = CombineListClasses(default=10, sequence=[1,2,3], value=3)
>>> a.new_method()
3
>>> a[5] = 1
>>> a
[1, 2, 3, 10, 10, 1]
"""
pass
# Derive from both classes in reverse, reversing the call chain order.
class CombineListClasses2(DefaultList, AddMethodToList):
"""
>>> a = CombineListClasses2(default=10, sequence=[1,2,3], value=3)
>>> a.new_method()
3
>>> a[5] = 1
>>> a
[1, 2, 3, 10, 10, 1]
"""
pass
if __name__ == '__main__':
import doctest
print doctest.testmod()
请注意,在Python 3中,语言直接支持:
class DefaultList(list):
def __init__(self, *args, default=None, **kwargs):
self.default = default
super(self).__init__(*args, **kwargs)
但是在Python 2中不支持。http://www.python.org/dev/peps/pep-3102