In Python everything is an object, and the key division is mutable vs immutable. Mutable objects (list, dict, set) can be changed in place; immutable ones (int, float, str, tuple) cannot — 'changing' them makes a new object. Combined with the fact that variables are references, this explains most Python surprises.
Mutable vs immutable, is vs ==
Immutable: int, float, bool, str, tuple, frozenset — can't be altered after creation. Mutable: list, dict, set — can. == compares value (are they equal?); is compares identity (are they the same object in memory?).
Mutability in action
s = "hi" s += "!" # str is immutable -> s now points to a NEW object nums = [1, 2] nums.append(3) # list is mutable -> changed IN PLACE; same object a = [1, 2] b = a # b refers to the SAME list b.append(3) print(a) # [1, 2, 3] -- a 'sees' the change (aliasing)
is vs ==
x = [1, 2, 3] y = [1, 2, 3] print(x == y) # True -- same contents print(x is y) # False -- different objects in memory
⚡ The edge
- == compares value; is compares identity (same object). Two lists with equal contents are == but not is. Use is only for singletons like None (if x is None).
- Assigning a mutable object doesn't copy it — both names refer to the same object. Changing it through one name is visible through the other (aliasing). To get an independent copy, use list(x), x[:], or copy.deepcopy for nested structures.
Worked example
What's the difference between mutable and immutable types in Python?
- Immutable objects (int, str, tuple) can't be changed after creation; any 'modification' creates a new object.
- Mutable objects (list, dict, set) can be changed in place, keeping the same identity.
- This matters for aliasing (shared references), function arguments, and using objects as dict keys (keys must be immutable/hashable).
Answer: Immutable types (int, str, tuple) can't change in place; mutable types (list, dict, set) can — affecting aliasing and hashability.
Worked example
What is the difference between 'is' and '=='?
- == calls the equality comparison: do the two objects have equal value?
- is checks identity: are they literally the same object in memory (same id)?
- Two distinct lists with equal contents are == but not is. Use 'is' for None checks, '==' for value comparison.
Answer: '==' compares value/equality; 'is' compares identity (same object). Use 'is' only for None and other singletons.
⚠ Watch out
- Aliasing: b = a on a list doesn't copy — both names share one object.
- Using is for value comparison is a bug — it may work for small cached ints/strings and then fail; use ==.
- Mutable default arguments (covered later) persist across calls — a notorious trap rooted in mutability.