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