Если в массиве под списком остались свободные места, то метод
.append(item) выполнится за константное время — достаточно записать новое значение в свободную ячейку и увеличить счетчик элементов на 1:def append(self, item):
self.array[self.length] = item
self.length += 1
Но что делать, если массив уже заполнен?
Приходится выделять память под новый массив, побольше, и копировать все элементы старого массива в новый (картинка прилагается).
Примерно так:
def append(self, item):
if self.length == self.capacity:
self._resize(self.capacity*2)
self.array[self.length] = item
self.length += 1
def _resize(self, new_cap):
new_arr = (new_cap * ctypes.py_object)()
for idx in range(self.length):
new_arr[idx] = self.array[idx]
self.array = new_arr
self.capacity = new_cap
_resize() — затратная операция, так что новый массив создают с запасом. В примере выше новый массив в два раза больше старого, а в питоне используют более скромный коэффициент — примерно 1.12.Если удалить из списка больше половины элементов через
.pop(), то питон его скукожит — выделит новый массив поменьше и перенесет элементы в него.Таким образом, список все время жонглирует массивами, чтобы это не приходилось делать нам ツ