Skip to content

Instantly share code, notes, and snippets.

@honno
Last active December 8, 2020 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save honno/b8d9f6aa23e87f95effbf9611ad883d9 to your computer and use it in GitHub Desktop.
Save honno/b8d9f6aa23e87f95effbf9611ad883d9 to your computer and use it in GitHub Desktop.
Reference implementation of the list with defaults, defaultlist
from collections import defaultdict
from collections.abc import Sequence, MutableSequence
class defaultlist(MutableSequence):
def __init__(self, default_factory=None):
self._ddict = defaultdict(default_factory or defaultlist._none_factory)
@staticmethod
def _none_factory():
return None
@property
def default_factory(self):
return self._ddict.default_factory
@default_factory.setter
def default_factory(self, default_factory):
self._ddict.default_factory = default_factory or defaultlist._none_factory
def __getitem__(self, key):
if isinstance(key, int):
i = self._actualise_index(key)
return self._ddict[i]
elif isinstance(key, slice):
start = key.start or 0
stop = key.start or 0
step = key.step or 1
if key.start is None:
start = 0 if step > 0 else len(self)
else:
start = self._actualise_index(key.start)
if key.stop is None:
stop = len(self) if step > 0 else 0
else:
stop = self._actualise_index(key.stop)
srange = range(start, stop, step)
dlist = defaultlist(self._ddict.default_factory)
dlist.extend(self._ddict[i] for i in srange)
return dlist
def __setitem__(self, i, v):
i = self._actualise_index(i)
self._ddict[i] = v
def __delitem__(self, i):
i = self._actualise_index(i)
try:
del self._ddict[i]
except KeyError:
pass
larger_keys = [k for k in self._ddict.keys() if k > i]
reindexed_subdict = {k - 1: self._ddict[k] for k in larger_keys}
for k in larger_keys:
del self._ddict[k]
self._ddict.update(reindexed_subdict)
def _actualise_index(self, i):
if i >= 0:
return i
else:
n = len(self)
if i >= -n:
return n + i
else:
raise IndexError("negative list index larger than list length, unresolvable")
def __len__(self):
try:
return max(self._ddict.keys()) + 1
except ValueError:
return 0
def __iter__(self):
for i in range(len(self)):
yield self._ddict[i]
def insert(self, i, v):
larger_keys = [k for k in self._ddict.keys() if k >= i]
reindexed_subdict = {k + 1: self._ddict[k] for k in larger_keys}
for k in larger_keys:
del self._ddict[k]
self._ddict.update(reindexed_subdict)
self._ddict[i] = v
def __repr__(self):
list_ = list(self)
return repr(list_)
def __str__(self):
return f"defaultlist({self.default_factory}, {repr(self)})"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment