In the last few posts, we’ve learned how to create lists (Post #46), access their items with indexing (Post #47), and extract sub-sections with slicing (Post #48). Now, we’re going to explore the single most important characteristic that defines how lists behave: mutability.
In this post, you’ll learn what it means for an object to be mutable (changeable) or immutable (unchangeable), and see why this property makes lists so dynamic and powerful.
Immutable vs. Mutable: What’s the Difference?
In programming, data types are often categorized as either mutable or immutable.
- Immutable: An object that cannot be changed after it is created. If you want to alter it, you must create a whole new object.
- Mutable: An object that can be changed “in-place” after it is created. You can modify its contents without creating a new object.
A Familiar Example of Immutability: Strings
You’ve been working with an immutable data type all along: the string. Once you create a string, you cannot change its individual characters.
Let’s say you want to change “Hello” to “Jello”. You might think you can just change the character at index 0.
my_string = "Hello"
# This will cause a TypeError!
# my_string[0] = "J"
Running this code will crash your program with a TypeError: 'str' object does not support item assignment
. This is Python’s way of telling you that strings are immutable. To “change” a string, you have to build a completely new one from the pieces you want.
my_string = "Hello"
# Slicing (from Post #48) creates a new string "ello"
new_string = "J" + my_string[1:]
print(new_string) # Output: Jello
print(my_string) # Output: Hello (The original is unchanged)
The Power of Mutability: Lists
Lists, on the other hand, are the primary mutable data structure we will work with. This means you can change their contents directly after they are created.
Let’s try the same operation on a list. We’ll change the second item in a list of numbers.
my_list = [10, 20, 30, 40]
print(f"Original list: {my_list}")
# Change the item at index 1
my_list[1] = 99
print(f"Modified list: {my_list}")
The output will be:
Original list: [10, 20, 30, 40]
Modified list: [10, 99, 30, 40]
The code runs without any errors! We didn’t create a new list; we modified the original one directly. The my_list
variable still points to the same list object, but the content of that object has been altered. This is “in-place” modification.
Why This Matters
Mutability is a fundamental concept in programming that has important consequences.
- Efficiency: Because lists are mutable, they are highly efficient for managing dynamic data. When you have a large collection that needs to change frequently (like a list of active users on a website), it’s much better to add or remove items from the existing list than to create a brand new copy for every small change.
- Shared References: It also means you have to be careful. If two variables refer to the same list, a change made through one variable will be visible through the other. We will explore this important “gotcha” in a future post.
What’s Next?
You now understand the crucial difference between immutable types like strings and mutable types like lists. The fact that lists can be changed in-place makes them incredibly flexible for managing collections of data that grow, shrink, or change over time.
Now that we know lists can be changed, it’s time to learn how. Python provides a set of powerful built-in methods for adding items to a list. In Post #50, we will explore the different ways to grow a list using .append()
, .insert()
, and .extend()
.
Author

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com