Python 3: Mutable, Immutable… Everything is Object!
Introduction
In Python, everything is an object. Whether you’re working with an integer, a string, a list, or even a function — they are all objects. This might sound abstract at first, but understanding this concept is fundamental to writing efficient and bug-free Python code.
This blog post explores how Python handles objects under the hood, the critical distinction between mutable and immutable types, and why this matters when you pass arguments to functions. If you’ve ever been surprised by a list changing “on its own” or wondered why two variables with the same integer seem to share the same identity — read on.
id and type
Every object in Python has three things: a value, a type, and an identity.
type()tells you what kind of object it is.id()tells you where in memory the object lives (its unique identity).
>>> a = 89
>>> type(a)
<class 'int'>
>>> id(a)
140234866486832>>> b = "Hello"
>>> type(b)
<class 'str'>
>>> id(b)
140234866486960Two variables can point to the same object in memory. You can check this with the is operator (which compares ids) versus == (which compares values):
>>> a = 89
>>> b = 89
>>> a == b
True
>>> a is b
True # Python caches small integers!
>>> id(a) == id(b)
True>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True # Same value
>>> a is b
False # Different objects in memory!Key takeaway: == checks equality of values, is checks identity (same object in memory).
Mutable Objects
Mutable objects can be modified after creation without changing their identity (their id stays the same).
Common mutable types: list, dict, set, bytearray.
>>> my_list = [1, 2, 3]
>>> id(my_list)
140234866250048>>> my_list.append(4)
>>> print(my_list)
[1, 2, 3, 4]
>>> id(my_list)
140234866250048 # Same id! The object was modified in place.This means that if two variables reference the same list, modifying one will affect the other:
>>> a = [1, 2, 3]
>>> b = a # b points to the SAME list object
>>> a.append(4)
>>> print(b)
[1, 2, 3, 4] # b is affected because a and b are the same object
>>> a is b
TrueImmutable Objects
Immutable objects cannot be modified after creation. Any operation that seems to “change” them actually creates a new object.
Get Valentin Planchon’s stories in your inbox
Join Medium for free to get updates from this writer.
Common immutable types: int, float, str, tuple, bool, frozenset.
>>> a = 89
>>> id(a)
140234866486832>>> a = a + 1
>>> print(a)
90
>>> id(a)
140234866486864 # Different id! A new object was created.The same applies to strings:
>>> s = "hello"
>>> id(s)
140234866120176>>> s = s + " world"
>>> id(s)
140234866121520 # New string object createdTuples are also immutable:
>>> t = (1, 2, 3)
>>> t[0] = 99
TypeError: 'tuple' object does not support item assignmentImportant note about Python’s integer caching: Python pre-caches small integers (typically -5 to 256) for performance. This is why:
>>> a = 256
>>> b = 256
>>> a is b
True # Same cached object>>> a = 257
>>> b = 257
>>> a is b
False # Different objects — outside the cache rangeWhy Does It Matter?
The mutable/immutable distinction has real consequences in your code:
1. Aliasing vs. Copying
With mutable objects, assignment creates an alias (a second reference to the same object):
>>> a = [1, 2, 3]
>>> b = a # Alias — same object
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4] # a is modified too!To get an independent copy, you must be explicit:
>>> a = [1, 2, 3]
>>> b = a[:] # Shallow copy using slicing
>>> b.append(4)
>>> print(a)
[1, 2, 3] # a is NOT modified
>>> print(b)
[1, 2, 3, 4]ith immutable objects, this problem doesn’t exist — since you can’t modify the object, “aliasing” is safe:
>>> a = 42
>>> b = a
>>> b = b + 1 # Creates a NEW int object
>>> print(a)
42 # a is unchanged2. Dictionary Keys
Only immutable (hashable) objects can be used as dictionary keys:
>>> d = {(1, 2): "tuple key"} # OK — tuple is immutable
>>> d = {[1, 2]: "list key"} # TypeError — list is mutableHow Arguments Are Passed to Functions
Python uses a mechanism often called “pass by object reference” (or “pass by assignment”). It’s neither pure pass-by-value nor pass-by-reference — it passes the reference to the object.
With immutable objects:
def increment(n):
n = n + 1 # Creates a new int object; local variable n is reassigned
print(f"Inside: n = {n}")a = 10
increment(a)
print(f"Outside: a = {a}")Output:
Inside: n = 11
Outside: a = 10 # a is unchanged — immutable objectThe function receives a reference to the integer 10. When n + 1 is computed, a new integer object 11 is created and assigned to the local variable n. The original variable a still points to 10.
With mutable objects:
def add_element(my_list):
my_list.append(4) # Modifies the object in place
print(f"Inside: {my_list}")a = [1, 2, 3]
add_element(a)
print(f"Outside: {a}")Output:
Inside: [1, 2, 3, 4]
Outside: [1, 2, 3, 4] # a IS modified — mutable objecthe function receives a reference to the same list. Since lists are mutable, .append() modifies the original object. Both the function's local variable and a point to the same list.
Reassignment inside a function:
However, if you reassign the variable inside the function (even with a mutable type), the original is not affected:
def replace_list(my_list):
my_list = [4, 5, 6] # Local reassignment — new object
print(f"Inside: {my_list}")a = [1, 2, 3]
replace_list(a)
print(f"Outside: {a}")Output:
Inside: [4, 5, 6]
Outside: [1, 2, 3] # a is unchanged — the local variable was reassignedPractical implication:
If you want a function to work on a list without modifying the original, pass a copy:
def safe_modify(my_list):
my_list = my_list[:] # Work on a copy
my_list.append(4)
return my_lista = [1, 2, 3]
b = safe_modify(a)
print(a) # [1, 2, 3] — unchanged
print(b) # [1Conclusion
Understanding that everything in Python is an object — and knowing whether that object is mutable or immutable — is essential for writing predictable code. The key takeaways:
id()gives an object's memory identity;type()gives its class.- Mutable objects (lists, dicts, sets) can be changed in place — beware of aliasing.
- Immutable objects (int, str, tuple) create new objects on “modification” — safe from side effects.
- Python passes references to objects, not copies. This means mutable objects can be modified inside functions, while immutable ones cannot.
Knowing these fundamentals will save you from subtle bugs and help you write cleaner, more intentional Python code.





