Understanding Objects, Identity, Mutability, and Memory Management in Python
Introduction Python is a powerful and flexible language, but to use it effectively, we need to understand how it handles objects, references, and memory. This post explores key concepts such as object identity, mutability, and how arguments are passed to functions, providing essential knowledge for writing efficient and bug-free Python code. What is an Object in Python? In Python, everything is an object: integers, strings, lists, functions, and even classes. Each object has three main properties: Identity → It is a unique number that identifies it in memory, which can be retrieved using id(obj). Type → Defines what kind of object it is, obtained with type(obj). Value → The actual data stored within the object. Example: x = 10 # 10 es un objeto entero print(id(x)) # Muestra la identidad del objeto print(type(x)) # Muestra que es un entero Difference Between a Class and an Object (Instance) Class: A blueprint for creating objects. Object (Instance): It is a concrete version created from a class. Example: class Dog: def __init__(self, name): self.name = name fido = Dog("Fido") # 'fido' is an instance of the Dog class Object Identity id() The id() function returns the memory address of an object. Example: x = 42 print(id(x)) # Displays a number (memory address) Does id() Always Stay the Same? For immutable objects (int, float, str, tuple, bool), modifying them generally creates a new object with a new id. However, due to Python's interning, small integers (-5 to 256) and some strings may retain the same id. For mutable objects (list, dict, set), modifying them keeps the id the same # Immutable object a = 10 print(id(a)) #Initial ID a += 1 print(id(a)) # New ID # Mutable object lst = [1, 2, 3] print(id(lst)) lst.append(4) print(id(lst)) # Same ID Checking Identity and Equivalence == checks if values are equal. is checks if two variables refer to the same object in memory. a = [1, 2, 3] b = a c = [1, 2, 3] print(a == b) # True (values are equal) print(a is b) # True (same memory address) print(a == c) # True (values are equal) print(a is c) # False (different objects in memory) Interning (Memory Optimization) Python optimizes memory by reusing immutable objects in certain cases. Integers (-5 to 256) Small integers (typically between -5 and 256) are interned, meaning they are stored once in memory and reused to improve performance. a = 89 b = 89 print(a is b) # True (same memory address) Strings (simple literals) Python can also apply interning to certain immutable strings, especially when they are short, alphanumeric, and created directly in the code (e.g., s = "hello"). However, dynamically constructed strings (s = "he" + "llo") or those containing special characters may not be automatically interned. s1 = "hello" s2 = "hello" print(s1 is s2) # True (interning applied) Mutability Mutability refers to whether an object's state can be changed after it is created. Mutable vs Immutable Objects A mutable object can change its contents after it is created. An immutable object cannot. For immutable types, modifying a value usually creates a new object. However, due to interning, Python may reuse small integers and simple strings. Immutable Types int, float, str, tuple, bool, frozenset, complex Mutable Types list, dict, set, bytearray Mutable example: lst = [1, 2, 3] lst.append(4) print(lst) # [1, 2, 3, 4] Immutable example: tup = (1, 2, 3) tup[0] = 100 # ❌ Error! Tuples are immutable Reassignment vs Mutation When you reassign a variable, you are not modifying the object itself but rather making the variable point to a new object in memory. This is especially relevant for immutable objects, where any modification results in reassignment rather than mutation. Mutation l1 = [1, 2, 3] l2 = l1 # Both variables point to the same list in memory l1.append(4) # The same object is modified print(l2) # [1, 2, 3, 4] ✅

Introduction
Python is a powerful and flexible language, but to use it effectively, we need to understand how it handles objects, references, and memory. This post explores key concepts such as object identity, mutability, and how arguments are passed to functions, providing essential knowledge for writing efficient and bug-free Python code.
What is an Object in Python?
In Python, everything is an object: integers, strings, lists, functions, and even classes. Each object has three main properties:
Identity → It is a unique number that identifies it in memory, which can be retrieved using
id(obj)
.Type → Defines what kind of object it is, obtained with
type(obj)
.Value → The actual data stored within the object.
Example:
x = 10 # 10 es un objeto entero
print(id(x)) # Muestra la identidad del objeto
print(type(x)) # Muestra que es un entero
Difference Between a Class and an Object (Instance)
Class: A blueprint for creating objects.
Object (Instance): It is a concrete version created from a class.
Example:
class Dog:
def __init__(self, name):
self.name = name
fido = Dog("Fido") # 'fido' is an instance of the Dog class
Object Identity id()
The id()
function returns the memory address of an object.
Example:
x = 42
print(id(x)) # Displays a number (memory address)
Does id()
Always Stay the Same?
For immutable objects (
int
,float
,str
,tuple
,bool
), modifying them generally creates a new object with a new id. However, due to Python's interning, small integers (-5 to 256) and some strings may retain the same id.For mutable objects (
list
,dict
,set
), modifying them keeps the id the same
# Immutable object
a = 10
print(id(a)) #Initial ID
a += 1
print(id(a)) # New ID
# Mutable object
lst = [1, 2, 3]
print(id(lst))
lst.append(4)
print(id(lst)) # Same ID
Checking Identity and Equivalence
==
checks if values are equal.is
checks if two variables refer to the same object in memory.
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a == b) # True (values are equal)
print(a is b) # True (same memory address)
print(a == c) # True (values are equal)
print(a is c) # False (different objects in memory)
Interning (Memory Optimization)
Python optimizes memory by reusing immutable objects in certain cases.
Integers (-5 to 256)
Small integers (typically between -5 and 256) are interned, meaning they are stored once in memory and reused to improve performance.
a = 89
b = 89
print(a is b) # True (same memory address)
Strings (simple literals)
Python can also apply interning to certain immutable strings, especially when they are short, alphanumeric, and created directly in the code (e.g., s = "hello"). However, dynamically constructed strings (s = "he" + "llo") or those containing special characters may not be automatically interned.
s1 = "hello"
s2 = "hello"
print(s1 is s2) # True (interning applied)
Mutability
Mutability refers to whether an object's state can be changed after it is created.
Mutable vs Immutable Objects
A mutable object can change its contents after it is created. An immutable object cannot.
For immutable types, modifying a value usually creates a new object. However, due to interning, Python may reuse small integers and simple strings.
Immutable Types
-
int
,float
,str
,tuple
,bool
,frozenset
,complex
Mutable Types
-
list
,dict
,set
,bytearray
Mutable example:
lst = [1, 2, 3]
lst.append(4)
print(lst) # [1, 2, 3, 4]
Immutable example:
tup = (1, 2, 3)
tup[0] = 100 # ❌ Error! Tuples are immutable
Reassignment vs Mutation
When you reassign a variable, you are not modifying the object itself but rather making the variable point to a new object in memory. This is especially relevant for immutable objects, where any modification results in reassignment rather than mutation.
Mutation
l1 = [1, 2, 3]
l2 = l1 # Both variables point to the same list in memory
l1.append(4) # The same object is modified
print(l2) # [1, 2, 3, 4] ✅