Skip to content

Instantly share code, notes, and snippets.

@Elizafox
Created November 24, 2017 18:31
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 Elizafox/0b9f28e5147da99098ce848ac701bd21 to your computer and use it in GitHub Desktop.
Save Elizafox/0b9f28e5147da99098ce848ac701bd21 to your computer and use it in GitHub Desktop.
from itertools import zip_longest
class ListSlices:
"""A basic template for how to implement slice support for list-like
objects.
This exploits the fact that the semantics of range() are the same as
list slices.
"""
def __getitem__(self, item, value):
if isinstance(item, slice):
indices = item.indices(len(self))
return [self[i] for i in range(*indices)]
# Non-slice case
raise NotImplementedError
def __setitem__(self, item, value):
if isinstance(item, slice):
len_self = len(self)
len_value = len(value)
indices = item.indices(len_self)
# Slice length
len_slice = (indices[1] - indices[0]) // indices[2]
if len_slice > len_value and indices[2] != 1:
# Mimicking default Python list behaviour
e = ("attempt to assign sequence of size {} to extended "
"slice of size {}").format(len_value, len_slice)
raise ValueError(e)
# NOTE:
# vi is the index of the unpacked value
# v is the value we are unpacking
# i is the range of the indicies
for (vi, v), i in zip_longest(enumerate(value), range(*indices)):
if i is None:
# i will be None if the range is exhausted before we run
# out of values to unpack, so make a provision for that.
# This mimics Python's default behaviour.
i = vi + indices[1]
if i >= len_self:
# If we're about to exceed array length, append onto
# ourselves. If you don't implement an append() operation,
# you'll want to change this to something equivalent (or
# raise an error).
self.append(v)
else:
self[i] = v
return
# Non-slice case
raise NotImplementedError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment