Здесь следует отметить две вещи:
- Когда REPL обнаруживает объект, он использует свой метод
__repr__
для представления. - Ваш метод
__str__
вызоветошибки, потому что он не возвращает строку.
После запуска вашего кода можно наблюдать следующее поведение:
>>> s.stack
>>> ['Plate 1', 'Plate 2', 'Plate 3']
>>> print(s)
[...]
TypeError: __str__ returned non-string (type list)
>>> repr(s)
>>> '<__main__.Stack object at 0x7fe358f7e240>'
Чтобы исправить эти проблемы, внедрите __repr__
, дляПример, подобный следующему:
def __repr__(self):
return repr(self.stack)
Теперь
>>> s
>>> ['Plate 1', 'Plate 2', 'Plate 3']
показывает содержимое s.stack
.Кроме того, вы можете удалить метод __str__
, так как при печати __repr__
будет вызываться как запасной вариант, когда нет реализации __str__
.
>>> del Stack.__str__
>>> print(s)
['Plate 1', 'Plate 2', 'Plate 3']
Если вы хотите сохранить __str__
, убедитесь, что изменили его для возврата объекта str
, в противном случае вы получите TypeError
, как показано выше.
Немного больше о __repr__
:
В идеале метод должен возвращать строку, чтобы при вставке копии в интерпретатор создавался равный объект.Поскольку ваш метод __init__
не принимает аргументов, здесь невозможно отобразить информативную строку, которая будет оценена как экземпляр Stack
, и одновременно показать содержимое стека.
Если вы изменили __init__
на
def __init__(self, iterable=None):
if iterable is None:
self.stack = []
else:
self.stack = list(iterable)
, вы можете изменить __repr__
на
def __repr__(self):
return 'Stack({!r})'.format(self.stack)
, который будет выглядеть следующим образом при реализации:
>>> s
>>> Stack(['Plate 1', 'Plate 2', 'Plate 3'])
... eval'ing этой строки создаст Stack
с тем же содержимым.
Пока мы в этом, рассмотрим реализацию __eq__
для хорошей меры ...
def __eq__(self, other):
return isinstance(other, Stack) and self.stack == other.stack
... такой, что:
>>> s == eval(repr(s))
>>> True