Stack data structure in Python 3 I have implemented a stack in Python 3, and it works well. If anything needs to be improved, I would appreciate the criticism.

class Stack:

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

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

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

        def pop(self):
            data = self.stack[-1]
            del self.stack[-1]
            return data

        def peek(self):
            return self.stack[-1]

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

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.sizeStack())
print("Popped: ", stack.pop())
print("Popped: ", stack.pop())
print(stack.sizeStack())
print("Peek:", stack.peek())
print(stack.sizeStack())
From a pure Python standpoint, a list is already a stack if you narrow its methods down to only pop and append.
l.append(x) will put x at the end of the list, and l.pop() will remove the last element of the list and return it.

So generally speaking, when you need a stack in Python, you'll just make a list and use append and pop.
The same goes for queues, but you'd use l.pop(0) instead of l.pop().

Considering this, I would say it's just plain unpythonic to implement a stack structure; instead, just use a list, that really is a dequeue and thus can be used as both a stack and a queue.



That said, I understand that append is not the common naming for the stack structure, and that push makes the intent of the method more clear.
Therefore, I would implement a stack as a direct subclass of list, and just "rename" the append method:

class Stack(list):
    def push(self, x):
        super().append(x)


If I wanted to make it more fool-proof, I'd also override pop so that it cannot take a parameter, unlike list.pop

class Stack(list):
    ...
    def pop(self):
        return super().pop()


Now the operation performed by the peek method can usually be done by stack[-1] (where stack is an instance of Stack), but it could be implemented just as follows:

class Stack(list):
    ...
    def peek(self):
        return self[-1]




Addendum

Some comments advising against subclassing list came out, notably mentioning the "composition over inheritance" principle.
That was an enriching discussion, and I'd like to amend my answer accordingly.

I'm no expert in design patterns, but as I understand it, this principle advocates the use of composition instead of inheritance to provide more flexibility.
One benefit of composition here is clearly to provide a cleaner API, with only the common stack methods and not insert, remove and so on that come from list and have no sense for stacks.

On the other hand, the inheritance I suggested happens to violate Liskov's substitution principle.
Although there's no problem with adding push and peek methods with respect to this principle, my implementation changes the signature of the pop method, which is not allowed by this principle.

From this perspective, I think that not only composition is valid here and adds in the benefit of a clean API, but also that inheritance is plain incorrect here.
Therefore, if I were forced to implement a stack class in Python, I'd go with composition and do as follows:

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

    def push(self, x):
        self._data.append(x)

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

    def peek(self)
        return self._data[-1]

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


But again, as I said, I would never do that in real life because a list can already serve as a stack, and stack = [] would perfectly convey how stack would be intended to be used.



References:

On the Liskov substitution principle:


https://en.wikipedia.org/wiki/Liskov_substitution_principle
https://stackoverflow.com/q/56860/7051394


On composition over inheritance:


https://en.wikipedia.org/wiki/Composition_over_inheritance
https://stackoverflow.com/a/53354/7051394 (also happens to mention Liskov principle)