有没有\你将如何构建一个相当于 python 的非常有用的collections.defaultdict
?
想象一下这样一个容器的用法:
>>> a = collections.defaultlist(0)
>>> a[2]=7
>>> a[4]='x'
>>> a
[0,0,7,0,'x']
更新:我添加了一个后续问题,为这个构造添加更多功能
有没有\你将如何构建一个相当于 python 的非常有用的collections.defaultdict
?
想象一下这样一个容器的用法:
>>> a = collections.defaultlist(0)
>>> a[2]=7
>>> a[4]='x'
>>> a
[0,0,7,0,'x']
更新:我添加了一个后续问题,为这个构造添加更多功能
我认为这使用起来会有点混乱;但是,这是我对如何做到这一点的第一个想法:
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)
这需要一个可调用的(我认为这就是 defaultdict 的工作方式)作为默认值。
当我运行时:
a = defaultlist(int)
print a
a[2] = 7
a[4] = 'x'
print a
我回来了:
[]
[0, 0, 7, 0, 'x']
如果您只需要索引访问而不是切片/追加等,那么只需使用defaultdict
.
(如果你真的想要 perl / js 语义,你可以继承 list__get__
和__set__
)
我的建议:
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']
@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)
也许最简单的方法是使用字典:
>>> 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']