-5
class Stack(object):

    def __init__(self):
        self.stack = []

    def __str__(self):
        return self.stack

    def push(self, item):
        self.stack.append(item)

    def pop(self):
        popped = self.stack.pop()
        print(popped)

    def isEmpty(self):
        if len(self.stack) == 0:
            print("True")
        else:
            print("False")

    def __len__(self):
        return len(self.stack)

I am trying to have the list returned when I call upon the object in interactive mode. This is what keeps happening:

>>> s = Stack()
>>> s.push("Plate 1")
>>> s.push("Plate 2")
>>> s.push("Plate 3")
>>> s
<__main__.Stack object at 0x0000017E06ED4E10>
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    The list is in `s.stack`. `s` is just an object without a `__repr__`. – timgeb Nov 13 '18 at 21:41
  • Do you mean that you want the string representation to list the contents of your stack? In which case you should define `__repr__` on your class. – khelwood Nov 13 '18 at 21:42
  • "I am trying to have the list returned when I call upon the object in interactive mode" - first, those words don't mean what you're trying to say. Second, what you're trying to do is a recipe for horrible confusion. It'd be better to display something like `Stack(['Plate 1', 'Plate 2', 'Plate 3'])`, with a constructor that accepts arguments like that. – user2357112 Nov 13 '18 at 21:42
  • When you type a variable in interactive mode it prints `repr(s)`, not `str(s)`. – Barmar Nov 13 '18 at 21:42
  • The `__str__` method should always return a string. – Barmar Nov 13 '18 at 21:43

5 Answers5

1

I think the methodology you may be looking for is documented here: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables

Modified example code:

class Stack:
    stack_list = []
    def __init__(self, name):
        self.name = name
    def push(self, item):
        self.stack_list.append(item)

The 'push' method appends items to the 'stack_list' when it's called.

stack = Stack('the_stack')
stack.push('example1')
stack.push('example2')
stack.push('example3')
stack.stack_list
['example1', 'example2', 'example3']
Enviy
  • 71
  • 7
0

The Python interactive shell prints the representation, not the string, so you need to implement a __repr__ method. But both __str__ and __repr__ should always return a string. So try:

def __str__(self):
    return str(self.stack)

def __repr__(self):
    return repr(self.stack)
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

I'd suggest first to override __repr__ instead of __str__ to match your goal, however below you can find both approaches for the class:

class Stack(object):
    def __init__(self):
        self.stack = []
    def __str__(self):
        return str(self.stack)
    def __repr__(self):
        return repr(self.stack)
    def push(self, item):
        self.stack.append(item)
    def pop(self):
        popped = self.stack.pop()
        print(popped)
    def isEmpty(self):
        if len(self.stack) == 0:
            print("True")
        else:
            print("False")
    def __len__(self):
        return len(self.stack)

Basically, what happened earlier you were triggering the representation of the object which is what you've called when you simply put s.

To have it transform to, let's say, a string representation you could do:

def __str__(self):
    return str(self.stack)

Analogously, you could do it for __repr__.

A example of its execution:

>>> s = Stack()
>>> print(s)
[]
>>> s.push(1)
>>> print(s) #this uses __str__
[1]
>>> s  #this uses __repr__
[1]

For deeper reference on the differences among them, you could check following thread Difference between __str__ and __repr__?

Rafael Aguilar
  • 3,084
  • 1
  • 25
  • 31
0

There are two things to note here:

  1. When the REPL evals an object, it uses its __repr__ method for presentation.
  2. 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
timgeb
  • 76,762
  • 20
  • 123
  • 145
0

Instead of returning the 'self.stack' from the __str__() function, you can return the list as shown below:

class Stack(object):

def __init__(self):
    self.stack = []

def __str__(self):
    return str(list(plates for plates in self.stack))

def push(self, item):
    self.stack.append(item)

def pop(self):
    popped = self.stack.pop()
    print(popped)

def isEmpty(self):
    if len(self.stack) == 0:
        print("True")
    else:
        print("False")

def __len__(self):
    return len(self.stack)

s = Stack()
s.push("Plate 1")
s.push("Plate 2")
s.push("Plate 3")
print(s)

Output:

['Plate 1', 'Plate 2', 'Plate 3']
Rish
  • 804
  • 8
  • 15
  • What's the point of calling `list()` on a list comprehension? And why do you need to make a copy when calling `str()`? – Barmar Nov 13 '18 at 22:11
  • Yes, right. Returning str(self.stack) from __str__() function will also work. – Rish Nov 13 '18 at 22:21