Introduction
Hello! In our last lesson, we concluded our exploration of sorting algorithms by comparing their performance trade-offs. You learned that there's no single "best" algorithm and that the right choice depends on factors like memory constraints, the need for stability, and guaranteed worst-case performance. We briefly mentioned that recursive algorithms like Merge Sort and Quicksort use something called the "call stack" to manage function calls.
That was a perfect segue into our next major topic: linear data structures. These are structures that store data in a sequential order. Today, we'll start with the very data structure that makes recursion possible: the stack.
Your learning outcome for this lesson is to describe the stack data structure (LIFO) and implement one using a Python list. We'll cover what a stack is, the principle that governs it, its core operations, and how to build one easily using tools you already know.
1. What is a Stack? The LIFO Principle
At its core, a data structure is simply a way of organizing and storing data to perform operations on it efficiently. A stack is one of the simplest data structures, and you've encountered its organizing principle many times in real life.
Think about a stack of books or plates. You add new items to the top, and when you take an item, you also take it from the top. You can't easily grab the plate at the bottom without removing all the ones on top of it first. This behavior is known as LIFO: Last-In, First-Out. The last item you add is the first one you can remove.
Python Stacks - Python Tutorial for Absolute Beginners | Mosh
To get a clear understanding of the stack concept and its LIFO principle, watch the beginning of this video from Programming with Mosh. He uses some great, easy-to-understand analogies.
Watch the video from the beginning until 01:16. Pay attention to the 'stack of books' and 'browser history' examples, as they perfectly illustrate the Last-In, First-Out idea.
As you saw, the browser's back button is a perfect software example. Each new page you visit is added to the "top" of a stack. When you click "back", the most recently visited page (the last one in) is removed (the first one out), taking you to the previous page.
2. The Core Operations of a Stack
To work with a stack, we use a standard set of operations with specific names. Understanding this terminology is important as it's used universally, regardless of the programming language.
- Push: Adds a new element to the top of the stack.
- Pop: Removes the top element from the stack.
- Peek (or Top): Looks at the top element of the stack without removing it.
Crucially, all of these operations work only on the top of the stack. This constraint is what defines the stack data structure.
Stacks in Python Tutorial - Data Structures for Coding Interviews
This short video from Codebagel clearly defines the three main stack operations and mentions their efficiency, which connects back to our work on algorithm analysis.
Watch from the start to 00:49. The video introduces the plate analogy and then defines Push, Pop, and Peek. Note the mention that these are O(1) operations—they take a constant amount of time, no matter how large the stack is.
The O(1) or "constant time" complexity for these operations is what makes stacks so efficient for the problems they are designed to solve. Adding, removing, or checking the top item is an extremely fast operation.
3. Implementing a Stack in Python
Python doesn't have a built-in data type called stack. However, the list object you're already familiar with provides all the functionality we need to create a perfectly good stack. The dynamic nature of Python lists (they can grow and shrink) makes them a natural fit.
Here’s how the stack operations map to Python list methods:
- Push: We use the
list.append()method. This adds an element to the end of the list, which we'll treat as our "top". - Pop: We use the
list.pop()method without any arguments. This removes and returns the last element of the list—exactly what we need for a LIFO structure. - Peek: To see the top element without removing it, we can access the last element of the list using the index
[-1]. - Check if Empty: We can check if the list is empty. An empty list evaluates to
Falsein a boolean context, so we can simply useif not my_stack:.
This image provides a great visual summary of the concept.

Now, let's see this in action.
Python Stacks - Python Tutorial for Absolute Beginners | Mosh
Let's continue with the Programming with Mosh video. He will now show you how to implement the browser history stack using a simple Python list.
Watch from 01:16 to 04:02. He demonstrates how to use .append() to push, .pop() to pop, and [-1] to peek at the top. He also shows how to check if the stack is empty to avoid errors.
4. Putting It All Together: A Code Example
The video demonstrated the implementation in an interactive way. It's also good practice to see how you might structure this logic inside a program.
For a more formal view, you can review this article. It recaps the LIFO principle and presents a Python implementation where stack operations are wrapped in functions—a common and clean way to organize your code.
This article from Programiz provides a concise summary and a structured code example.
First, quickly read the sections 'Stack Data Structure', 'LIFO Principle of Stack', and 'Basic Operations of Stack' to reinforce the concepts. Then, in the 'Stack Implementations' section, click the 'Python' tab and review the code. Notice how they use functions like push() and pop() that operate on the stack list.
Here is a simple, self-contained example you can run yourself. It combines the ideas from the resources into a single script.
# 1. Initialize an empty list to act as our stack
tasks = []
print(f"Stack initialized: {tasks}")
print(f"Is stack empty? {not tasks}") # `not []` is True
# 2. Push (append) items onto the stack
print("\nPushing tasks...")
tasks.append("Write code")
print(f"Stack state: {tasks}")
tasks.append("Create tests")
print(f"Stack state: {tasks}")
tasks.append("Refactor code")
print(f"Stack state: {tasks}")
print(f"Is stack empty? {not tasks}") # `not [...]` is False
# 3. Peek at the top item
# We should always check if the stack is not empty before peeking or popping
if tasks:
top_item = tasks[-1]
print(f"\nTop task (peek): {top_item}")
print(f"Stack state remains unchanged: {tasks}")
# 4. Pop items from the stack
print("\nPopping tasks...")
if tasks:
completed_task = tasks.pop()
print(f"Completed task: {completed_task}")
print(f"Stack state: {tasks}")
if tasks:
completed_task = tasks.pop()
print(f"Completed task: {completed_task}")
print(f"Stack state: {tasks}")
# 5. Pop the last item and check for emptiness
if tasks:
completed_task = tasks.pop()
print(f"Completed task: {completed_task}")
print(f"Stack state: {tasks}")
print(f"\nIs stack empty now? {not tasks}")
# 6. Attempting to pop from an empty stack
# The `if tasks:` check prevents this! If we didn't have it, tasks.pop() would cause an IndexError.
if not tasks:
print("No more tasks to pop. Stack is empty.")
Your Turn: Copy the code above into your editor, run it, and make sure you understand the output at each step. Try adding a few more push (append) and pop operations to solidify your understanding.
Conclusion
Great work! You've just learned and implemented your first formal data structure. While simple, the stack is a fundamental building block in computer science, used in everything from parsing expressions in a calculator to managing memory and program execution.
Key Takeaways:
- A stack is a linear data structure that follows the Last-In, First-Out (LIFO) principle.
- The main operations are Push (add to top), Pop (remove from top), and Peek (view the top). These are all
O(1)operations. - In Python, a stack can be easily and efficiently implemented using a list.
list.append()performs a push.list.pop()performs a pop.list[-1]performs a peek.if not my_list:checks if the stack is empty.
Preview of the Next Lesson:
Now that you know how to build a stack, the next step is to use it to solve a problem. In our next lesson, we will tackle a classic technical interview question: checking for balanced parentheses in a string (e.g., is "{[()]}" valid?). You'll see how the stack's LIFO property makes it the perfect tool for this job.