There are two things to note here:
- When the REPL evals an object, it uses its
__repr__ method for presentation.
- Your
__str__ method will cause errors because it does not return a string.
After running your code, the following behavior can be observed:
>>> s.stack
>>> ['Plate 1', 'Plate 2', 'Plate 3']
>>> print(s)
[...]
TypeError: __str__ returned non-string (type list)
>>> repr(s)
>>> '<__main__.Stack object at 0x7fe358f7e240>'
To fix these issues, implement __repr__, for example like this:
def __repr__(self):
return repr(self.stack)
Now
>>> s
>>> ['Plate 1', 'Plate 2', 'Plate 3']
shows the content of s.stack. In addition, you can remove the __str__ method, because when printing, __repr__ will be called as a fallback when there's no __str__ implementation.
>>> del Stack.__str__
>>> print(s)
['Plate 1', 'Plate 2', 'Plate 3']
If you want to keep __str__, make sure to modify it in order to return a str object, otherwise you'll get a TypeError as demonstrated above.
A little more about __repr__:
Ideally, the method should return a string such that when copy pasted into the interpreter, an equal object will be built. Since your __init__ method accepts no arguments, it's not possible here to display an informative string that would be evaluated as an instance of Stack and show the content of the stack at the same time.
If you changed __init__ to
def __init__(self, iterable=None):
if iterable is None:
self.stack = []
else:
self.stack = list(iterable)
you could change __repr__ to
def __repr__(self):
return 'Stack({!r})'.format(self.stack)
which would look like this when implemented:
>>> s
>>> Stack(['Plate 1', 'Plate 2', 'Plate 3'])
... eval'ing this string would create a Stack with the same content.
While we're at it, consider implementing __eq__ for good measure...
def __eq__(self, other):
return isinstance(other, Stack) and self.stack == other.stack
... such that:
>>> s == eval(repr(s))
>>> True