Sitemap
Press enter or click to view image in full size

Understanding Mutable and Immutable Objects in Python

5 min readNov 1, 2024

--

Python treats data as objects, from basic integers to complex lists. In this post, we’ll dive into the key differences between mutable and immutable objects, why these distinctions matter, and how Python’s handling of them can impact the way you write code. As a software engineering student, it’s essential to understand the efficiency and flexibility provided by these concepts, especially in complex applications.

id and type

Each object in Python has a unique identity (an id) and a type, which defines what kind of data it holds and its allowed operations. The id can be seen using id() and tells us the memory location of an object, while type() shows its data type. For instance:

python
a = 10
print(id(a), type(a)) # Outputs the id (memory location) and <class 'int'>

Objects’ ids are useful in understanding how Python reuses or allocates memory based on whether an object is mutable or immutable.

Mutable Objects

Mutable objects, such as lists and dictionaries, can be modified after they are created. This means you can change, add, or remove items without creating a new object.

python
lst = [1, 2, 3]
print(id(lst)) # Memory address before modification
lst.append(4)
print(id(lst)) # Same memory address after modification

In the example, the id remains the same, showing that Python allows modifications to the original object itself.

Immutable Objects

Immutable objects, such as integers, strings, and tuples, cannot be changed once created. Any modification creates a new object in memory.

python
num = 10
print(id(num)) # Initial memory address
num += 1
print(id(num)) # New memory address after modification

The id changes when num is modified, indicating that Python created a new object instead of altering the original.

Why It Matters: Mutable vs. Immutable in Python

The difference in Python’s treatment of mutable and immutable objects helps with memory management and performance. Immutable objects, being fixed, are often faster to access and require less memory management. Meanwhile, mutable objects, due to their flexibility, can be beneficial in data structures that require frequent changes.

Get Ntare GAMA Allan’s stories in your inbox

Join Medium for free to get updates from this writer.

Knowing this distinction helps us write efficient code. For example, we use tuples (immutable) when we need a fixed collection of items, while lists (mutable) are preferred when we plan to modify the collection frequently.

How Python Passes Arguments to Functions

In Python, arguments are passed by “assignment,” which behaves differently for mutable and immutable objects. Immutable objects are “copied” by reference, meaning any function using them doesn’t alter the original object. Mutable objects, however, can be modified within functions, affecting the original.

python
def modify_item(item):
item.append(100) # This will affect the original list

lst = [1, 2, 3]
modify_item(lst)
print(lst) # Output: [1, 2, 3,100] - Original list is modified

On the other hand, with immutable types like integers:

python
def modify_value(value):
value += 10

num = 5
modify_value(num)
print(num) # Output: 5 - Original value remains unchanged

In Python, assignment and referencing are related but have distinct meanings:

Assignment
- Assignment in Python means binding a variable to a specific object or value.
- For example, in `x = 5`, Python assigns the integer `5` to the variable `x`.
- After the assignment, `x` acts as a reference to the object `5`, but the object `5` itself remains unchanged by merely assigning it to `x`.

Referencing
- Referencing means pointing a variable to an existing object, not creating a new one.
- If `y = x`, `y` is now a reference to the same object `x` is referencing.
- No new copy of the object is created; `x` and `y` point to the same memory location. If the object they reference is mutable (like a list), changes to the object through one variable will be reflected in the other.

Example 1;
python
Assignment
x = [1, 2, 3] # x is assigned a list object [1, 2, 3]

Referencing
y = x # y references the same list that x does, no new list is created

Modifying the object through y
y.append(4) # Since x and y refer to the same list, changes through y affect x
print(x) # Output: [1, 2, 3, 4]
print(y) # Output: [1, 2, 3, 4]

In this example, `y = x` makes `y` a reference to the list object in `x`. Because they reference the same object, changes made to the list via `y` are also visible through `x`.

NSMALLPOSINTS and NSMALLNEGINTS

In Python’s internals, `NSMALLPOSINTS` and `NSMALLNEGINTS` are part of a caching mechanism used to optimize the handling of small integers. Here’s what they represent:

NSMALLPOSINTS (Number of Small Positive Integers)
- This refers to the range of small positive integers (typically `0` to `256`) that Python caches for efficiency.
- When you use a small integer in this range, Python doesn’t create a new integer object; instead, it reuses a pre-existing, cached object.
- For example, each instance of `x = 10` in Python doesn’t create a new integer object for `10` — it reuses the same, cached object, making it memory-efficient.

NSMALLNEGINTS (Number of Small Negative Integers)
- `NSMALLNEGINTS` serves the same purpose for small negative integers, though this range is generally limited and might be from `-5` to `-1`.
- Python doesn’t use as wide a range for negative integers as it does for positive integers in its caching mechanism.

Why These Exist
The caching of small integers allows Python to improve performance and memory usage, especially in loops or situations with frequent use of these integers. Since integers are immutable in Python, reusing the same object is safe and efficient.

Press enter or click to view image in full size

In practice, this means small integer values are generally very efficient to work with in Python, while larger integers (outside the cached range) are still created as distinct objects when needed.

Conclusion

Understanding mutable and immutable objects is crucial in Python, as it affects memory use, code efficiency, and data integrity. By mastering these concepts, i was able to write code that is both optimal and functionally appropriate for different situations.

--

--