Stacks with a List: Push, Pop and Peek
22 min · Intermediate
Need help? Ask a tutor on WhatsApp (opens in a new tab)A stack is a pile where only the top moves. Browsers use one for the Back button, editors use one for undo, and Python uses one to keep track of function calls. A plain list already works as a stack.
Last in, first out
Stack is a collection where items are added and removed at one end only, called the top. The last item pushed is the first item popped, which is called last in, first out (LIFO).
A pile of invoices on a desk is a stack. You add a new invoice on top and you take the top one first. The newest item always leaves first.
A list is already a stack
Python's append adds at the end of a list and pop() removes from the end. Both take O(1) time, so the end of a list is the top of the stack.
stack = []stack.append("login")stack.append("cart")stack.append("payment")print(stack[-1])print(stack.pop())print(stack)Example 1 · Undo history
history = []for action in ["type A", "type B", "delete B"]: history.append(action)
while history: print("undo", history.pop())undo delete B undo type B undo type A
What this code does
- Actions are pushed in the order they happen, so the latest one is on top.
- Popping until the list is empty undoes them newest first.
Example 2 · Reverse a word with a stack
word = "orders"stack = list(word)reversed_word = ""while stack: reversed_word += stack.pop()print(reversed_word)print(word[::-1])sredro sredro
What this code does
- Pushing every letter and popping them all reverses the order.
- Slicing with
[::-1]is the short Python way. The stack version shows the idea that the next lessons use.
stack[-1] looks at the top without removing it. This is called a peek. pop() removes and returns the top.
Guard the empty stack
Calling pop() on an empty list raises IndexError, and so does stack[-1]. An empty list is falsy, so if stack: is the standard check before you read the top.
stack = []if stack: print(stack.pop())else: print("nothing to undo")Example 3 · Pop only when there is something
stack = [10, 20]for _ in range(3): if stack: print("popped", stack.pop()) else: print("stack is empty")popped 20 popped 10 stack is empty
What this code does
- The third pop would raise
IndexError, so theif stack:check prints a message instead. - Checking first is clearer than catching the error after it happens.
Guard first, then pop. Do not wrap every pop in try when a plain if stack: says the same thing.
A small Stack class
Interviews often ask for a class with push, pop, peek and is_empty. The class hides the list so callers cannot break the stack rule.
class Stack: def __init__(self): self._items = []
def push(self, item): self._items.append(item)
def pop(self): return self._items.pop()
def peek(self): return self._items[-1]
def is_empty(self): return not self._itemsExample 4 · Using the Stack class
class Stack: def __init__(self): self._items = []
def push(self, item): self._items.append(item)
def pop(self): return self._items.pop()
def peek(self): return self._items[-1]
def is_empty(self): return not self._items
tickets = Stack()tickets.push("T-101")tickets.push("T-102")print(tickets.peek())print(tickets.pop())print(tickets.pop())print(tickets.is_empty())T-102 T-102 T-101 True
What this code does
peekleaves the top in place andpopremoves it.- After two pops the stack is empty, so
is_emptygivesTrue.
Example 5 · Back and forward with two stacks
back, forward = [], []current = "home"for page in ["products", "cart"]: back.append(current) current = page
forward.append(current)current = back.pop()print("now at", current)print("back stack", back)print("forward stack", forward)now at products back stack ['home'] forward stack ['cart']
What this code does
- Going back pushes the current page on the forward stack and pops one from the back stack.
- A browser history is two stacks working together.
Example 6 · An explicit stack instead of recursion
def flatten(data): flat = [] stack = [data] while stack: item = stack.pop() if isinstance(item, list): stack.extend(item) else: flat.append(item) flat.reverse() return flat
print(flatten([1, [2, [3, 4]], 5]))[1, 2, 3, 4, 5]
What this code does
- A list is pushed back as its items. A number goes to the result.
- Items come out in reverse order, so the result is reversed once at the end. The same job with recursion would use Python's own call stack.
Every method is O(1). In everyday Python code a plain list is enough, and the class is for when an interviewer asks for one.
Next step
Check your understanding
10 quick questions