Understanding Python's Mutable and Immutable Objects: Memory Management and Function Argument Passing
Introduction:
In Python, an object is a fundamental concept representing a data structure with both data (attributes or properties) and behaviour (methods or functions). This includes simple data types like integers and strings, as well as more complex data structures such as lists, dictionaries, classes, and instances of classes.Objects are instances of classes, and classes act as blueprints or templates for creating objects. When you create an object, you’re creating an instance of a particular class, which means the object inherits the attributes and behaviours defined in that class.
Objects play a central role in storing and manipulating data. Objects in Python can be categorized as either mutable or immutable, and understanding the distinction between the two is crucial for writing efficient and bug-free code. In this blog post, we'll learn? the concepts of mutable and immutable objects, explore how they are stored in memory, discuss the difference between assignment and referencing, and shed light on how Python manages variables when passed to functions.
ID and Type:
In Python, each object is assigned a unique identifier (ID) upon creation. The ID serves as an address in memory where the object is stored. The `id()` function can be used to retrieve an object's ID, providing a unique value for each object. Objects are also associated with a specific data type that defines their behavior and the operations that can be performed on them.
Mutable Objects:
Mutable objects are those whose internal state can be changed after creation. Common examples of mutable objects include lists, dictionaries, sets, and user-defined classes. For instance, Below is examples of mutable object:?
Sets: sets are mutable collections of unique elements and you can modify the using various set of operations
my_set = {1, 2, 3}
my_set.add(4) # Modifies the set by adding a new element
print(my_set) # Output: {1, 2, 3, 4}
# Removing an element from the set
my_set.remove(3)
print(my_set) # Output: {1, 2, 4}
Dictionaries: Dictionaries are mutable mappings that can be modified by adding, updating or removing key-value pairs.
person = {"name": "John", "age": 30}
person["occupation"] = "Engineer" # Adds a new key-value pair
print(person) # Output: {'name': 'John', 'age': 30, 'occupation': 'Engineer'}
# Updating an existing key's value
person["age"] = 32
print(person) # Output: {'name': 'John', 'age': 32, 'occupation': 'Engineer'}
# Removing a key-value pair
del person["occupation"]
print(person) # Output: {'name': 'John', 'age': 32}
List: Lists are mutable objects that allow modifications after creation.
fruits = ["apple", "banana", "orange"]
fruits.append("grape") # Modifies the list by adding a new element
print(fruits) # Output: ['apple', 'banana', 'orange', 'grape']
# Slicing creates a new list, but the original list remains unchanged
sliced_fruits = fruits[1:3]
print(sliced_fruits) # Output: ['banana', 'orange']
Immutable Objects:
x = 10
y = x # y points to the same integer object as x
y += 5 # A new integer object is created with the value 15 and y points to it
print(x) # Output: 10 (x remains unchanged)
print(y) # Output: 15 (new object created)
name = "Alice"
name += " Smith" # Concatenation creates a new string object
领英推荐
print(name) # Output: "Alice Smith"
my_tuple = (1, 2, 3)
# Attempting to modify the tuple will raise an error
my_tuple[0] = 0 # TypeError: 'tuple' object does not support item assignment
Difference between Assignment and Referencing:
In Python, the assignment involves creating a new reference to an existing object. For example:
x = [1, 2, 3]
y = x
Here, both `x` and `y` refer to the same list object, so any changes made through one variable will affect the other. Referencing, on the other hand, involves creating a reference to an object without making a new copy. For example:
a = [1, 2, 3]
b = a[:] # Creates a new copy of the list using slicing
In this case, `a` and `b` refer to different list objects, and changes to one won't affect the other.
Variable Management when Passing to a Function:
When passing variables to functions in Python, the values are either passed by reference or by value. Immutable objects are passed by value, creating a new copy within the function's scope. However, mutable objects are passed by reference, meaning that changes made within the function are reflected in the original object outside the function.
Memory Storage of Immutable Objects:
When dealing with immutable objects, Python uses a memory optimization technique known as "interning." Integers in the range of -5 to 256 and commonly used strings are interned. This means that they are stored in a pre-allocated memory area, ensuring that each instance of a particular value shares the same memory address. For example, if you create multiple variables with the same value for an integer within the range of -5 to 256, they will point to the same memory location.
Integer Pre-allocation and Aliases:
Python optimizes memory allocation for integers within a specific range. The range is determined by the `NSMALLPOSINTS` and `NSMALLNEGINTS` constants. Integers within this range are pre-allocated and shared, creating aliases to the same object when appropriate. This mechanism enhances performance and reduces memory consumption.
Why it Matters and Python's Treatment of Mutable and Immutable Objects:
Understanding the distinction between mutable and immutable objects is vital for designing robust and efficient programs. Immutable objects guarantee data integrity and prevent unintended changes. Python treats mutable objects with caution, especially when passed to functions, as modifications within a function can have unintended side effects on the original object.
Argument Passing to Functions:
When an immutable object, such as an integer, float, string, or tuple, is passed as an argument to a function, a copy of the object's value is created and passed to the function. This means that any modifications made to the object inside the function will not affect the original object outside the function. The original object remains unchanged.
def modify_immutable(x):
x = x + 1
return x
num = 5
result = modify_immutable(num)
print(num) # Output: 5 (original object remains unchanged)
print(result) # Output: 6 (modified value returned from the function)
When a mutable object, such as a list, dictionary, set, or user-defined class, is passed as an argument to a function, the function receives a reference to the original object's memory location. This means that any modifications made to the object inside the function will directly affect the original object outside the function. The original object is modified in place.
def modify_mutable(my_list):
my_list.append(4)
my_list = [1, 2, 3]
modify_mutable(my_list)
print(my_list) # Output: [1, 2, 3, 4] (original list modified inside the function)
In conclusion, grasping the concept of mutable and immutable objects in Python is fundamental for writing clean, efficient, and bug-free code. Understanding how objects are stored in memory, the difference between assignment and referencing, and how function argument passing behaves for mutable and immutable objects empowers developers to make informed decisions when designing Python applications. Proper utilization of these concepts can lead to more efficient code, better memory management, and fewer potential pitfalls.
Security Architect | Software Engineer | Researcher | Consultant
2 个月Good read.