From 0d65b8a9388cd696720686b2e1069e870c768b30 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Tue, 16 Apr 2024 13:15:24 +0300 Subject: [PATCH] + 3.8_08 --- mod_oop/3.8_08_stack.py | 183 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 mod_oop/3.8_08_stack.py diff --git a/mod_oop/3.8_08_stack.py b/mod_oop/3.8_08_stack.py new file mode 100644 index 0000000..4047c01 --- /dev/null +++ b/mod_oop/3.8_08_stack.py @@ -0,0 +1,183 @@ +""" + https://stepik.org/lesson/701993/step/8?unit=702094 + + Ранее вы уже создавали стек-подобную структуру, когда один объект ссылается на следующий и так по цепочке до последнего: + +Для этого в программе объявлялись два класса: +StackObj - для описания объектов стека; +Stack - для управления стек-подобной структурой. + +И, далее, объекты класса StackObj следовало создавать командой: +obj = StackObj(data) +где data - это строка с некоторым содержимым объекта (данными). При этом каждый объект класса StackObj должен иметь следующие локальные атрибуты: +data - ссылка на строку с данными, указанными при создании объекта; +next - ссылка на следующий объект класса StackObj (при создании объекта принимает значение None). + +Класс Stack предполагается использовать следующим образом: +st = Stack() # создание объекта стек-подобной структуры +В каждом объекте класса Stack должен быть локальный публичный атрибут: +top - ссылка на первый объект стека (если стек пуст, то top = None). + +А в самом классе Stack следующие методы: +push(self, obj) - добавление объекта класса StackObj в конец стека; +pop(self) - извлечение последнего объекта с его удалением из стека; + +Дополнительно в классе Stack нужно объявить магические методы для обращения к объекту стека по его индексу, например: +obj_top = st[0] # получение первого объекта +obj = st[4] # получение 5-го объекта стека +st[2] = StackObj("obj3") # замена прежнего (3-го) объекта стека на новый +Если индекс не целое число или число меньше нуля или больше числа объектов в стеке, то должно генерироваться исключение командой: +raise IndexError('неверный индекс') + +Пример использования классов Stack и StackObj (эти строчки в программе не писать): +st = Stack() +st.push(StackObj("obj1")) +st.push(StackObj("obj2")) +st.push(StackObj("obj3")) +st[1] = StackObj("new obj2") +print(st[2].data) # obj3 +print(st[1].data) # new obj2 +res = st[3] # исключение IndexError +P.S. В программе нужно объявить только классы. Выводить на экран ничего не нужно. +""" + +from typing import List + + +class StackObj: + def __init__(self, data=None): + self.__next = None + self.__data = data + + @property + def data(self): + return self.__data + + @data.setter + def data(self, value): + self.__data = value + + @property + def next(self): + return self.__next + + @next.setter + def next(self, value): + if isinstance(value, (self.__class__, None.__class__)): + self.__next = value + + def __repr__(self): + return f"{self.__class__.__name__}({self.data!r})" + + def __str__(self): + return str(self.data) + + +class Stack: + def __init__(self, data=None): + self.top = None + if not data: + return + for x in map(lambda x: isinstance(x, StackObj) and x or StackObj(x), data): + self.push(x) + + @property + def bottom(self) -> StackObj: + curr, last = self.top, None + while curr: + curr, last = curr.next, curr + return last + + def push(self, obj: StackObj): + if not self.top: + self.top = obj + else: + self.bottom.next = obj + + def __len__(self): + count, obj = 0, self.top + while obj: + obj, count = obj.next, count + 1 + return count + + def __getitem__(self, idx: int) -> StackObj: + if not isinstance(idx, int) or not 0 <= idx < len(self): + raise IndexError("неверный индекс") + count, obj = 0, self.top + while obj: + if count == idx: + return obj + obj, count = obj.next, count + 1 + + def __setitem__(self, idx: int, value: StackObj): + if not isinstance(idx, int) or not 0 <= idx <= len(self): + raise IndexError("неверный индекс") + + if not isinstance(value, StackObj): + value = StackObj(value) + + if idx == len(self): + self.push(value) + return + + old = self[idx] + value.next = old.next + + if idx > 0: + self[idx - 1].next = value + else: + self.top = value + + def pop(self) -> StackObj: + if not self.top: + return None + + a, b, c = [self.top] + [None] * 2 + while a: + a, b, c = a.next, a, b + + if c: + c.next = None + + if self.top in [b, c]: + self.top = None + + return b + + def get_data(self) -> List[StackObj]: + return [x for x in self] + + def __repr__(self): + return f"{self.__class__.__name__}({self.get_data()!r})" + + def __str__(self): + return " -> ".join(self.get_data()) + + +def tests(): + code = ( + b"b95j*AX9WctYfoZoC?ao" + + b"SYB4e*DJcqbbS`jpb7&}2bYWv_Phx5)B5z`9F*715DGGCRTQOZAJs?wbVPk7gVrnQNZ(?dPEpBCZ" + + b"A}I=Cb8}^KbRctdTQFTNWMOn+AU!=GB5z`9F)<<_VQyp~b97rVT`pu{bYUPpJs=`)VrnuiZe@2OE" + + b"FdD#u+f6ifY7+mvC)Ikf*@pJbYURSzRNRC0A?3T13_WjYEVARr)Nb8}^KbRb4" + + b"yY;$ESAR^Gc(6u1ZfzY$iwa~rLwb6jkxY2;nzRA9cW7yBWguue3LqdLAYpTJWpZ>NX>)0Ab97;DV`V64EFe>KVPk7gVrnTYAR^G" + + b"d(6P~q(6!LI(Sjh+fzg7{wa~iIuprR1(7w>S(6-RE(7hngvC)gsg3*j1(T&i$(6`XF(7e#U(7Vx(" + + b"(SXpt(7Yhfy3o7Ou+f3hfzYrZQ*>ctYfoZoA_^cNARulaD?K1F3LqdLAZQ>xAZRXbWq5Q7ARr(h3" + + b"So0|WpZ>NZXi89ATlf