Вы можете избежать нарушения принципа подстановки Лискова, создав класс, который наследуется от collection.MutableSequence, который является абстрактным классом.Это будет выглядеть примерно так:
class MyList(collections.MutableSequence):
def __init__(self, l=[]):
if type(l) is not list:
raise ValueError()
self._inner_list = l
def __len__(self):
return len(self._inner_list)
def __delitem__(self, index):
self._inner_list.__delitem__(index - 1)
def insert(self, index, value):
self._inner_list.insert(index - 1, value)
def __setitem__(self, index, value):
self._inner_list.__setitem__(index - 1, value)
def __getitem__(self, index):
return self._inner_list.__getitem__(index - 1)
Здесь есть одна проблема (хотя может быть и больше).Если вы индексируете свой новый список следующим образом:
l = MyList()
l[0]
, вы фактически позвоните:
self._inner_list[-1]
, что даст вам последний элементТаким образом, вы должны выполнить дополнительную проверку в методах и убедиться, что вы ведете обратное индексирование, если хотите, чтобы эта функция была для вашего списка.это новый код, который, я считаю, не должен иметь никаких проблем.
def indexing_decorator(func):
def decorated(self, index, *args):
if index == 0:
raise IndexError('Indices start from 1')
elif index > 0:
index -= 1
return func(self, index, *args)
return decorated
class MyList(collections.MutableSequence):
def __init__(self):
self._inner_list = list()
def __len__(self):
return len(self._inner_list)
@indexing_decorator
def __delitem__(self, index):
self._inner_list.__delitem__(index)
@indexing_decorator
def insert(self, index, value):
self._inner_list.insert(index, value)
@indexing_decorator
def __setitem__(self, index, value):
self._inner_list.__setitem__(index, value)
@indexing_decorator
def __getitem__(self, index):
return self._inner_list.__getitem__(index)
def append(self, value):
self.insert(len(self) + 1, value)