How can I overload the __repr__ method to display all items in a linked list Stack?

Viewed 141

I've created my Node and Stack classes, but I can't figure out how I can display the repr in the Stack class in order to be able to print all items currently in the stack? I've been trying to concatenate the nodes but I'm not sure how since the Stack() doesn't allow iterating through the way a list does?

The stack works as it should, I just don't know how to display it's contents?

Here is my code:

class Stack:
    class Node:
        def __init__(self, elem, next):
            self.elem = elem
            self.next = next
        
        def __repr__(self):
            return str(self.elem)
    
    def __init__(self):
        self._stack = None
        self._size  = 0
        
    
    def __repr__(self):
        # *Not sure how to implement this properly*
        s = ''
        for i in range(self._size):
            last = self._stack.elem
            s += (str(last))+ ', '
            self._stack.elem = self._stack.next
        return 
    
    def push(self, elem):
        if self._stack == None:
            self._stack = self.Node(elem, None)
            self._size += 1 
        else: 
            self._stack = self.Node(elem, self._stack)
            self._size += 1 
    
    def pop(self):
        if self._stack == None:
            raise Exception ('This Stack is empty!')
        else: 
            last = self._stack.elem
            self._stack = self._stack.next
            self._size -= 1
        return last
    
    def top(self):
        return  self._stack.elem
    
    def isEmpty(self):
        return self._size == 0

Example:

s= Stack()
s.push(4)
s.push(9)
s.push("joe")
s
joe, 9, 9, 

Thank you in advance.

1 Answers

A way simpler implementation that avoids all the problems and pitfalls of your solution:

from typing import Iterable, Any


class Stack:
    def __init__(self, xs: Iterable = None):
        self._items = [] if xs is None else list(xs)

    def push(self, elem: Any):
        self._items.append(elem)

    def pop(self) -> Any:
        return self._items.pop()

    def top(self) -> Any:
        return self._items[-1]

    def isEmpty(self) -> bool:
        return not self._items

    def __repr__(self) -> str:
        typename = type(self).__name__
        return f'{typename}({self._items})'

    def __str__(self) -> str:
        return ', '.join(str(x) for x in self._items)


s = Stack()
s.push(4)
s.push(9)
s.push("joe")
print(s)
print(repr(s))

But note that there's little use to a class like this over just using a list like a stack to begin with.

The output:

4, 9, joe
Stack([4, 9, 'joe'])

Note that this has the top element at the end, you could reverse it if you like of course.

If you insist on a working __repr__ for your specific implementation, using __repr__ as you intend in a non-standard way, something like this would work:

    def __repr__(self):
        p = self._stack
        elems = []
        while p is not None:
            elems.append(p.elem)
            p = p.next
        return ', '.join(elems)

But note that there's several other issues with your implementation, other than this not being a correct __repr__, as previously pointed out here and in the comments. Your 'node' has a __repr__ which just returns its element value (which isn't a valid representation at all in most cases); you seem to be using __repr__ where you're really after __str__.

If this were an assignment in programming class, I'm not sure I'd award a passing grade, depending on what the aim was.

Related