""" https://stepik.org/lesson/701988/step/7?unit=702089 Объявите класс LinkedList (связный список) для работы со следующей структурой данных: Здесь создается список из связанных между собой объектов класса ObjList. Объекты этого класса создаются командой: obj = ObjList(data) где data - строка с некоторой информацией. Также в каждом объекте obj класса ObjList должны создаваться следующие локальные атрибуты: __data - ссылка на строку с данными; __prev - ссылка на предыдущий объект связного списка (если объекта нет, то __prev = None); __next - ссылка на следующий объект связного списка (если объекта нет, то __next = None). В свою очередь, объекты класса LinkedList должны создаваться командой: linked_lst = LinkedList() и содержать локальные атрибуты: head - ссылка на первый объект связного списка (если список пуст, то head = None); tail - ссылка на последний объект связного списка (если список пуст, то tail = None). А сам класс содержать следующие методы: add_obj(obj) - добавление нового объекта obj класса ObjList в конец связного списка; remove_obj(indx) - удаление объекта класса ObjList из связного списка по его порядковому номеру (индексу); индекс отсчитывается с нуля. Также с объектами класса LinkedList должны поддерживаться следующие операции: len(linked_lst) - возвращает число объектов в связном списке; linked_lst(indx) - возвращает строку __data, хранящуюся в объекте класса ObjList, расположенного под индексом indx (в связном списке). Пример использования классов (эти строчки в программе писать не нужно): linked_lst = LinkedList() linked_lst.add_obj(ObjList("Sergey")) linked_lst.add_obj(ObjList("Balakirev")) linked_lst.add_obj(ObjList("Python")) linked_lst.remove_obj(2) linked_lst.add_obj(ObjList("Python ООП")) n = len(linked_lst) # n = 3 s = linked_lst(1) # s = Balakirev P.S. На экран в программе ничего выводить не нужно. """ class LinkedList: def __init__(self): self.head = None self.tail = None def add_obj(self, obj): if not self.head: self.head = obj self.tail = obj else: self.tail.next = obj obj.prev = self.tail self.tail = obj def __iter__(self): obj = self.head while obj and obj != self.tail.next: yield obj obj = obj.next def __reversed__(self): obj = self.tail while obj and obj != self.head.prev: yield obj obj = obj.prev def remove_obj(self, idx): if not self: pass elif idx == 0: self.head = self.head.next if self.head: self.head.prev = None elif idx == len(self) - 1: self.tail = self.tail.prev self.tail.next = None else: obj = self.head for _ in range(idx): obj = obj.next obj.prev.next = obj.next obj.next.prev = obj.prev if not self: self.head = self.tail = None def __len__(self): return sum(1 for _ in self) def __getitem__(self, idx): return next(filter(lambda x: x[0] == idx, enumerate(self)))[1] def __call__(self, key): return self[key].data def get_data(self): return [*map(ObjList.get_data, self)] class ObjList: def __init__(self, data=None): self.__next = None self.__prev = None self.__data = data def set_next(self, obj): self.__next = obj def set_prev(self, obj): self.__prev = obj def get_next(self): return self.__next def get_prev(self): return self.__prev def set_data(self, data): self.__data = data def get_data(self): return self.__data data = property(get_data, set_data) next = property(get_next, set_next) prev = property(get_prev, set_prev) def tests(): ln = LinkedList() ln.add_obj(ObjList("Сергей")) ln.add_obj(ObjList("Балакирев")) ln.add_obj(ObjList("Python ООП")) ln.remove_obj(2) assert ( len(ln) == 2 ), "функция len вернула неверное число объектов в списке, возможно, неверно работает метод remove_obj()" ln.add_obj(ObjList("Python")) assert ln(2) == "Python", "неверное значение атрибута __data, взятое по индексу" assert len(ln) == 3, "функция len вернула неверное число объектов в списке" assert ln(1) == "Балакирев", "неверное значение атрибута __data, взятое по индексу" n = 0 h = ln.head while h: assert isinstance(h, ObjList) h = h._ObjList__next n += 1 assert n == 3, "при перемещении по списку через __next не все объекты перебрались" n = 0 h = ln.tail while h: assert isinstance(h, ObjList) h = h._ObjList__prev n += 1 assert n == 3, "при перемещении по списку через __prev не все объекты перебрались" if __name__ == "__main__": import doctest doctest.testmod() tests()