class Stack:
    def __init__(self):
        self.top = None

    @property
    def bottom(self):
        curr, last = self.top, None
        while curr:
            curr, last = curr.next, curr
        return last

    def push(self, obj):
        if not self.top:
            self.top = obj
        else:
            self.bottom.next = obj

    def pop(self):
        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 c == self.top:
            self.top = None

        if self.top in [b, c]:
            self.top = None

        return b

    def get_data(self):
        result = []
        obj = self.top
        while obj:
            result.append(obj.data)
            obj = obj.next
        return result

    def __str__(self):
        return " -> ".join(self.get_data())


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})"


s = Stack()
top = StackObj("obj_1")
s.push(top)
s.push(StackObj("obj_2"))
s.push(StackObj("obj_3"))
s.pop()

res = s.get_data()
assert res == ["obj_1", "obj_2"], f"метод get_data вернул неверные данные: {res}"
assert s.top == top, "атрибут top объекта класса Stack содержит неверное значение"

h = s.top
while h:
    res = h.data
    h = h.next

s = Stack()
top = StackObj("obj_1")
s.push(top)
s.pop()
assert s.get_data() == [], f"метод get_data вернул неверные данные: {s.get_data()}"

n = 0
h = s.top
while h:
    h = h.next
    n += 1

assert n == 0, "при удалении всех объектов, стек-подобная стурктура оказалась не пустой"

s = Stack()
top = StackObj("name_1")
s.push(top)
obj = s.pop()
assert obj == top, "метод pop() должен возвращать удаляемый объект"