Back to Python
2026-02-135 min read

Stacks (Python Programming)

Learn Stacks (Python Programming) step by step with clear examples and exercises.

Why This Matters

Python stacks are a fundamental data structure that help manage and manipulate collections of items efficiently. This guide will delve into the core concept, provide a worked example, explore common mistakes, offer practice questions, and answer frequently asked questions about Python stacks.

The Importance of Stacks in Programming

  1. Efficient Data Management: Stacks allow you to add and remove items from the collection in a Last-In-First-Out (LIFO) manner, which is crucial when dealing with sequential data processing.
  2. Interview Preparation: Mastering Python stacks can help you excel in coding interviews, as they are often used in solving complex problems.
  3. Real-world Applications: Stacks are employed in various areas such as parsing expressions, creating undo/redo functions, and implementing algorithms like Depth-First Search (DFS) and Topological Sorting.
  4. Debugging Tools: Python debuggers often use stacks to keep track of function calls, making it easier for developers to identify and fix issues in their code.
  5. Learning Foundation: Understanding stacks is a stepping stone towards mastering more complex data structures like queues, trees, and graphs.

Prerequisites

Before diving into the core concept, ensure you have a solid understanding of:

  1. Basic Python syntax (variables, data types, operators)
  2. Control structures (if-else statements, loops)
  3. List comprehensions and built-in functions like append(), insert(), and pop()
  4. Understanding the concept of Big O notation for time complexity analysis

Core Concept

A stack is a linear data structure that follows the LIFO principle. It can be visualized as a pile of plates where you can only add or remove plates from the top. In Python, stacks are typically implemented using lists or deques.

Creating a Stack (Using List)

To create a stack, simply initialize an empty list:

stack = []

Or use the collections module's deque for optimized LIFO operations:

from collections import deque
stack = deque()

Pushing Elements onto the Stack (Adding)

You can add elements to the stack using the append() function for lists or appendleft() function for deques:

stack.append(element) # List
stack.appendleft(element) # Deque (adds element at the front)

Popping Elements from the Stack (Removing)

To remove the top element from the stack, use the pop() function for lists or popleft() function for deques:

top_element = stack.pop() # List
top_element = stack.popleft() # Deque (removes element at the front)

Peeking at the Top Element

You can check the top element without removing it using the [-1] index for lists or tail attribute for deques:

top_element = stack[-1] # List
top_element = stack.tail # Deque (returns the last item)

Stack Operations (Using List)

Here's a simple implementation of basic stack operations using lists:

def is_empty(stack):
return len(stack) == 0

def push(stack, element):
stack.append(element)

def pop(stack):
if not is_empty(stack):
return stack.pop()
else:
print("Stack is empty.")
return None

def peek(stack):
if not is_empty(stack):
return stack[-1]
else:
print("Stack is empty.")
return None

Stack Operations (Using Deque)

Here's the same implementation using deques for optimized LIFO operations:

def is_empty(stack):
return len(stack) == 0

def push(stack, element):
stack.appendleft(element)

def pop(stack):
if not is_empty(stack):
return stack.popleft()
else:
print("Stack is empty.")
return None

def peek(stack):
if not is_empty(stack):
return stack[-1] # Since deque has a tail and head, we use the last item instead of tail
else:
print("Stack is empty.")
return None

Worked Example

Let's implement a simple calculator using Python stacks to handle parentheses and perform operations in the correct order.

def calculate(expression):
stack = []
operators = {'+': 1, '-': 1, '*': 2, '/': 2}
precedence = {'*': 2, '/': 2, '+': 1, '-': 1}

for token in expression:
if token.isalnum():
stack.append(token)
elif token == '(':
stack.append(token)
elif token == ')':
top_operator = peek(stack)
while top_operator != '(' and not is_empty(stack):
result = operate(pop(stack), pop(stack))
stack.append(result)
if not is_empty(stack):
top_operator = peek(stack)
stack.pop()
elif token in operators:
while not is_empty(stack) and precedence[token] <= precedence[peek(stack)]:
result = operate(pop(stack), pop(stack))
stack.append(result)
stack.append(token)

return stack[0]

def operate(op1, op2):
if op1 == '+' or op1 == '-':
return eval(f"{op2} {op1}")
elif op1 == '*' or op1 == '/':
return eval(f"{op2} {op1}")

expression = "((2+3)*4)-5"
print(calculate(expression)) # Output: 14

Common Mistakes

  1. Forgetting to handle parentheses: Make sure you account for opening and closing parentheses in your stack implementation.
  2. Incorrect operator precedence: Ensure that you correctly implement the order of operations (PEMDAS) when dealing with multiple operators.
  3. Misusing append() and pop(): Be mindful of using append() to add elements and pop() to remove them, as they have different complexities in Python lists.
  4. Not checking if the stack is empty: Always check whether the stack is empty before attempting to perform operations on it.
  5. Using inappropriate data structures: While lists are commonly used for implementing stacks in Python, deques provide optimized LIFO operations and should be considered when dealing with large datasets or performance-critical applications.

Practice Questions

  1. Implement a function that checks if a given string is a valid expression using Python stacks and parentheses.
  2. Write a function that reverses a given list using Python stacks.
  3. Create a simple implementation of a postfix calculator using Python stacks.
  4. Compare the time complexity of basic stack operations when implemented using lists and deques in Python.
  5. Implement a depth-first search (DFS) algorithm using Python stacks to traverse a graph represented as an adjacency list.

FAQ

  1. Why use lists or deques to implement stacks in Python?

Lists are a built-in data structure in Python, making them easy to work with and efficient for implementing stacks. Deques provide optimized LIFO operations when dealing with large datasets or performance-critical applications.

  1. What is the time complexity of push and pop operations on a stack implemented using lists or deques in Python?

The append() function used for pushing elements onto the stack has a time complexity of O(1) for both lists and deques, while the pop() operation has a time complexity of O(n) for lists due to the need to traverse the list. The popleft() operation on deques has a constant time complexity of O(1). However, since stacks are typically small data structures, this difference is often negligible in practice.

  1. Can I implement a stack using other Python data structures like tuples or arrays?

Yes, you can implement stacks using tuples (using slicing for adding and removing elements) or arrays (using list-like syntax). However, lists and deques are more common choices due to their simplicity and efficiency.

Stacks (Python Programming) | Python | XQA Learn