Implementing Stack with Python

2019-06-16 20:32发布

I am trying to implement a simple stack with Python using arrays. I was wondering if someone could let me know what's wrong with my code.

class myStack:
     def __init__(self):
         self = []

     def isEmpty(self):
         return self == []

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

     def pop(self):
         return self.pop(0)

     def size(self):
         return len(self)

    s = myStack()
    s.push('1')
    s.push('2')
    print(s.pop())
    print s

10条回答
看我几分像从前
2楼-- · 2019-06-16 21:02

I corrected a few problems below. Also, a 'stack', in abstract programming terms, is usually a collection where you add and remove from the top, but the way you implemented it, you're adding to the top and removing from the bottom, which makes it a queue.

class myStack:
     def __init__(self):
         self.container = []  # You don't want to assign [] to self - when you do that, you're just assigning to a new local variable called `self`.  You want your stack to *have* a list, not *be* a list.

     def isEmpty(self):
         return self.size() == 0   # While there's nothing wrong with self.container == [], there is a builtin function for that purpose, so we may as well use it.  And while we're at it, it's often nice to use your own internal functions, so behavior is more consistent.

     def push(self, item):
         self.container.append(item)  # appending to the *container*, not the instance itself.

     def pop(self):
         return self.container.pop()  # pop from the container, this was fixed from the old version which was wrong

     def peek(self):
         if self.isEmpty():
             raise Exception("Stack empty!")
         return self.container[-1]  # View element at top of the stack

     def size(self):
         return len(self.container)  # length of the container

     def show(self):
         return self.container  # display the entire stack as list


s = myStack()
s.push('1')
s.push('2')
print(s.pop())
print(s.show())
查看更多
Anthone
3楼-- · 2019-06-16 21:02

I left a comment with the link to http://docs.python.org/2/tutorial/datastructures.html#using-lists-as-stacks, but if you want to have a custom type that gives you push, pop, is_empty, and size convenience methods, I'd just subclass list.

class Stack(list):
    def push(self, item):
        self.append(item)
    def size(self):
        return len(self)
    def is_empty(self):
        return not self

However, as I said in the comments, I'd probably just stick with a straight list here, as all you are really doing is aliasing existing methods, which usually only serves to make your code harder to use in the long run, as it requires people using it to learn your aliased interface on top of the original.

查看更多
疯言疯语
4楼-- · 2019-06-16 21:04

Your problem is that you're popping from the beginning of the list, when you should be popping from the end of the list. A stack is a Last-In First-Out data structure, meaning that when you pop something from it, that something will be whatever you pushed on last. Take a look at your push function - it appends an item to the list. That means that it goes at the end of the list. When you call .pop(0), however, you're removing the first item in the list, not the one you last appended. Removing the 0 from .pop(0) should solve your problem.

查看更多
We Are One
5楼-- · 2019-06-16 21:05

The proper implementation would include __iter__ also since Stack needs to be LIFO order.

class Stack:
    def __init__(self):
        self._a = []

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

    def pop(self):
        return self._a.pop()

    def isEmpty(self):
        return len(self._a) == 0

    def __iter__(self):
        return reversed(self._a)

    def __str__(self):
        # return str(list(reversed(self._a)))
        return str(list(iter(self)))

def main():
    stack = Stack()
    stack.push('a')
    stack.push('b')
    stack.push('c')
    stack.pop()
    print(stack)
    if stack:
        print("stack not empty")
    stack.pop()
    stack.pop()
    if stack.isEmpty():
        print("stack empty")

if __name__ == '__main__':
    main()
查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-06-16 21:06

Assigning to self won't turn your object into a list (and if it did, the object wouldn't have all your stack methods any more). Assigning to self just changes a local variable. Instead, set an attribute:

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

and use the attribute instead of just a bare self:

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

Also, if you want a stack, you want pop() rather than pop(0). pop(0) would turn your data structure into a(n inefficient) queue.

查看更多
相关推荐>>
7楼-- · 2019-06-16 21:07

I would like to share my version of the stack implementation that inherits Python List. I believe iteration on a stack should be happening in LIFO order. Additionally, an iteration on pop-all() should be provided to iterate while poping all elements. I have also added stack.clear() to empty a stack (like we have in deque.clear() in collections module). I have also override __repr__ for debugging purpose:

class Stack(list):

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

    def top(self):
        return self[-1]

    def size(self):
        return len(self)

    def isempty(self):
        return self.size() == 0

    def __iter__(self):
        """ iter in lifo """
        return super(Stack, self).__reversed__()

    def __reversed__(self):
        return super(Stack, self).__iter__()

    def popall(self):
        try:
            while True:
                yield self.pop()
        except IndexError:
            pass

    def clear(self):
        del self[:]

    def __repr__(self):
        if not self:
            return '%s()' % self.__class__.__name__
        return '%s(%s)' % (self.__class__.__name__, super(Stack, self).__repr__())

Here is how you can use it:

stack = Stack(range(5))
print "stack: ", stack  # stack:  Stack([0, 1, 2, 3, 4])

print "stack.pop() => ", stack.pop() # stack.pop() =>  4
print "stack.push(20) " # stack.push(20) 
stack.push(20)
for item in stack:
    print item  # prints 20, 3, 2... in newline
print "stack: ", stack # stack:  Stack([0, 1, 2, 3, 20])
print "stack pop all..."
for item in stack.popall(): # side effect to clear stack
    print item
print "stack: ", stack # stack:  Stack()

Primary, I implemented it to use to solve a programming problem next greater element.

查看更多
登录 后发表回答