问题
Is there\How would you build an equivalent of python's very useful collections.defaultdict?
Imagined usage of such a container:
>>> a = collections.defaultlist(0)
>>> a[2]=7
>>> a[4]='x'
>>> a
[0,0,7,0,'x']
UPDATE: I've added a follow up question to add even more functionality to this construct
回答1:
I think this would be a bit confusing to use; however, here's my first thought on how to do it:
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)
This takes a callable (I think that's how defaultdict works) for the default value.
When I run:
a = defaultlist(int)
print a
a[2] = 7
a[4] = 'x'
print a
I get back:
[]
[0, 0, 7, 0, 'x']
回答2:
If all you need is indexed access and not slicing / append, etc, then just use a defaultdict
.
(if you really want perl / js semantics on this, you could subclass list __get__
and __set__
)
回答3:
My proposal:
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__)
Results:
>>> 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']
回答4:
A slightly enhanced version from answer by @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)
回答5:
Perhaps the easiest way is using a dict:
>>> 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']
来源:https://stackoverflow.com/questions/8719558/defaultdict-equivalent-for-lists