I am trying to create defaultlist, by analogy with defaultdict. The idea is that sometimes I want a list that is pre-filled (virtually!) with some element at all indices for which the value is not explicitly set. The difference with defaultdict is that I do not actually add the default values to the list, unless I have to extend list due to user assignments.
1) Is there any problem with this design?
2) This is the implementation I’m going to use. Is there any issue with it?
class defaultlist(list):
def __init__(self, default_factory, arg = ()):
# note: cannot use arg = None since list(None) is not the same as list()
# alternatively can use:
# def __init__(self, default_factory, *args, **kwargs)
self.default_factory = default_factory
super().__init__(arg)
def __getitem__(self, key):
try:
return super().__getitem__(key)
except IndexError:
return self.default_factory()
def __setitem__(self, key, value):
for i in range(len(self), key):
self.append(self.default_factory())
self.append(value)
EDIT: Originally, I had two mistakes. Sorry, and thanks for pointing out both errors in the answers.
Problem.
Your
__init__function tries to forward all arguments to the base class. However, the way you are writing it can only forward 1 argument, and the constructor will always expect the 2nd argument. The proper way to do that in Python is:The
__setitem__function tries to fill all not-yet-existing indices, but you have missed thekeyitself — note thatrangeis exclusive in the end — therefore thesuper().__setitem__method will fail. You should use.appendin that case.