有没有\你如何建立一个非常有用的collections.defaultdict
等效的python?
想象一下这种容器的用法:
>>> a = collections.defaultlist(0)
>>> a[2]=7
>>> a[4]='x'
>>> a
[0,0,7,0,'x']
更新:我添加了follow up question以向此构造添加更多功能
答案 0 :(得分:10)
我认为使用它会有点混乱;然而,这是我第一次想到如何做到这一点:
class defaultlist(list):
def __init__(self, fx):
self._fx = fx
def __setitem__(self, index, value):
while len(self) <= index:
self.append(self._fx())
list.__setitem__(self, index, value)
这需要一个可调用的(我认为这是默认值的工作原理)默认值。
当我跑步时:
a = defaultlist(int)
print a
a[2] = 7
a[4] = 'x'
print a
我回来了:
[]
[0, 0, 7, 0, 'x']
答案 1 :(得分:3)
如果你需要的只是索引访问而不是切片/附加等,那么只需使用defaultdict
。
(如果你真的想要perl / js语义,你可以继承列表__get__
和__set__
)
答案 2 :(得分:2)
我的建议:
def xtend(f):
def wrap(self, index, *args):
if len(self) <= index:
self.extend([self._gen()] * (index - len(self) + 1))
return f(self, index, *args)
return wrap
class defaultlist(list):
def __init__(self, gen, lst = []):
list.__init__(self, lst)
self._gen = gen
__setitem__ = xtend(list.__setitem__)
__getitem__ = xtend(list.__getitem__)
结果:
>>> a = defaultlist(int, [1, 2, 3])
>>> a[10] = 'x'
>>> a[2] = 7
>>> print a
[1, 2, 7, 0, 0, 0, 0, 0, 0, 0, 'x']
答案 3 :(得分:1)
来自@Finn回答的略微增强的版本。
class defaultlist(list):
"""List returning default value when accessing uninitialized index.
Original implementation: http://stackoverflow.com/a/8719940/315168
"""
def __init__(self, fx):
self._fx = fx
def __setitem__(self, index, value):
while len(self) <= index:
self.append(self._fx())
list.__setitem__(self, index, value)
def __getitem__(self, index):
"""Allows self.dlist[0] style access before value is initialized."""
while len(self) <= index:
self.append(self._fx())
return list.__getitem__(self, index)
答案 4 :(得分:0)
也许最简单的方法是使用词典:
>>> a = {}
>>> a[2] = 7
>>> a[4] = 'x'
>>> [a[i] if i in a else 0 for i in xrange(max(a) + 1)]
[0, 0, 7, 0, 'x']