Mutability & Identity in Python
Before learning advanced Python, you must understand one question:
When you change a value, are you changing the object itself, or creating a new object?
Most beginner bugs around lists, functions, dictionaries, classes, and memory come from not understanding this.
This article explains:
Mutable vs Immutable Objects
Object Identity
id()Equality vs Identity
==vsisShared References
Aliasing
Side Effects of Mutation
From first principles.
1. The Fundamental Question
Imagine writing a name on a piece of paper.
You have two choices:
Option A
Erase the old name and write a new one on the same paper.
The paper stays the same.
Only the content changes.
Option B
Throw away the old paper.
Create an entirely new paper with the new name.
The content changes because the object itself changed.
Python objects behave the same way.
Some objects allow modification.
Some do not.
This leads us to the first concept.
2. Mutable vs Immutable Objects
First Principle
An object is either:
Mutable
Can change after creation.
Immutable
Cannot change after creation.
Analogy
Think about:
Mutable → Whiteboard
You can erase and rewrite.
Same board.
Different content.
Immutable → Printed Book
Cannot modify the printed text.
If you want different text, print a new book.
Common Immutable Types
int
float
bool
str
tuple
frozenset
Example:
x = 10
x = x + 1
Looks like modification.
But actually:
Create object
10Create object
11Make
xpoint to11
The object 10 never changed.
Common Mutable Types
list
dict
set
most custom objects
Example:
numbers = [1, 2, 3]
numbers.append(4)
The same list object changed.
No new list created.
3. Object Identity
First Principle
Every object in memory has an identity.
Identity answers:
"Which exact object is this?"
Not:
"What value does it contain?"
Analogy
Imagine two identical twins.
They may look identical.
But they are different people.
Identity is about who.
Not what.
Example:
a = [1, 2, 3]
b = [1, 2, 3]
Same values.
Different objects.
Memory:
a → List A
b → List B
Python treats them as separate objects.
4. id() — Seeing Identity
Python provides:
id()
to inspect object identity.
Example:
a = [1, 2, 3]
print(id(a))
Output:
140512839204416
(The number differs on every machine.)
Think of it as:
House Number
for an object.
Two different houses may look identical.
Their addresses differ.
Example:
a = [1, 2]
b = [1, 2]
print(id(a))
print(id(b))
Different identities.
Different objects.
5. Equality vs Identity
This is where many beginners get confused.
Equality
Asks:
"Do these objects contain the same value?"
Identity
Asks:
"Are these literally the same object?"
Analogy:
Two ₹500 notes.
Equal value?
Yes.
Same physical note?
No.
Example:
a = [1, 2, 3]
b = [1, 2, 3]
Values:
a == b
Result:
True
Because contents match.
Identity:
a is b
Result:
False
Because they are different objects.
6. == vs is
These operators answer different questions.
==
Checks value equality.
a == b
asks:
Do they contain the same data?
is
Checks identity.
a is b
asks:
Are they literally the same object?
Example:
a = [1, 2]
b = [1, 2]
print(a == b)
print(a is b)
Output:
True
False
Visualization:
a ──► [1,2]
b ──► [1,2]
Two objects.
Same values.
Different identities.
7. Shared References
Now things get interesting.
Example:
a = [1, 2, 3]
b = a
Many beginners think:
Copy happened
No.
Actual memory:
a ─┐
▼
[1,2,3]
▲
b ─┘
Both variables point to the same object.
Check:
a is b
Output:
True
Same object.
Same identity.
Same memory.
8. Aliasing
When multiple names refer to the same object:
a = [1, 2, 3]
b = a
This is called:
Aliasing
Analogy
You:
Aman
may also be called:
Friend
Student
Developer
Different names.
Same person.
Similarly:
a
b
are different names.
Same object.
9. Mutation Through Aliases
Now observe:
a = [1, 2, 3]
b = a
b.append(4)
print(a)
Output:
[1, 2, 3, 4]
Many beginners expect:
[1, 2, 3]
But that's wrong.
Why?
Because:
a and b
point to the same list.
Changing through one name changes the object.
The other name sees the same change.
Memory:
Before:
a ─┐
▼
[1,2,3]
▲
b ─┘
After:
a ─┐
▼
[1,2,3,4]
▲
b ─┘
10. Side Effects of Mutation
First Principle
A side effect happens when modifying an object affects code outside the current location.
Example:
def add_item(items):
items.append("Python")
courses = ["C"]
add_item(courses)
print(courses)
Output:
['C', 'Python']
Why?
Function parameter:
items
and variable:
courses
point to the same list.
Memory:
courses ─┐
▼
['C']
▲
items ───┘
Function mutates the list.
Caller sees the change.
This is one of the most common beginner bugs.
11. Avoiding Mutation Side Effects
Create a copy.
courses = ["C"]
new_courses = courses.copy()
new_courses.append("Python")
Now:
courses
remains unchanged.
Memory:
courses ─► ['C']
new_courses ─► ['C','Python']
Two separate objects.
12. Immutable Objects Behave Differently
Example:
x = 10
y = x
y += 5
Many people expect:
x = 15
Wrong.
Why?
Integers are immutable.
Python creates a new object.
Before:
x ─┐
▼
10
▲
y ─┘
After:
x ─► 10
y ─► 15
Original object unchanged.
13. Mental Model
Whenever you write Python, ask:
Question 1
Is this object mutable?
list, dict, set → Yes
int, str, tuple → No
Question 2
Am I creating a new object?
or
Am I modifying an existing object?
Question 3
Are multiple variables pointing to the same object?
b = a
If yes:
Mutation through one name affects all names.
Question 4
Do I care about value or identity?
Value:
==
Identity:
is
Final Takeaway
Everything in this chapter comes from one idea:
Variables do not store objects. Variables store references to objects.
Once you understand that:
Mutability becomes obvious
Identity becomes obvious
id()makes sense==vsisbecomes clearAliasing becomes predictable
Mutation side effects stop being mysterious
Think of variables as labels.
Think of objects as actual things.
Multiple labels can point to the same thing.
If that thing is mutable, changing it through one label changes it for everyone.

