Analysis of Multiple Assignment and Mutable Object Behavior in Python

Nov 21, 2025 · Programming · 11 views · 7.8

Keywords: Python Multiple Assignment | Mutable Objects | Shared References | Object Model | List Behavior

Abstract: This article provides an in-depth exploration of Python's multiple assignment behavior, focusing on the distinct characteristics of mutable and immutable objects. Through detailed code examples and memory model explanations, it clarifies variable naming mechanisms, object reference relationships, and the fundamental differences between rebinding and in-place modification. The discussion extends to nested data structures using 3D list cases, offering comprehensive insights for Python developers.

Python Naming Mechanism and Multiple Assignment Basics

In Python programming, understanding the essence of variable assignment is crucial. Unlike languages like C or Java, what are commonly called "variables" in Python are more accurately described as "names". When we execute a = b = c = [0, 3, 5], we are not creating three independent list objects, but rather making three different names—a, b, and c—all point to the same list object in memory.

Shared Reference Behavior with Mutable Objects

Consider the following code example:

a = b = c = [0, 3, 5]
a[0] = 1
print(a)  # Output: [1, 3, 5]
print(b)  # Output: [1, 3, 5]
print(c)  # Output: [1, 3, 5]

This result might confuse beginners, but it perfectly aligns with Python's object model. When executing a[0] = 1, we are not rebinding the name a; instead, we are accessing the list object pointed to by a and modifying its first element. Since b and c point to the same list object, they naturally reflect this change.

Object Identity and Reference Verification

To verify whether two names point to the same object, use the is operator:

>>> a = b = c = [0, 3, 5]
>>> a is b
True
>>> a is c
True

More deeply, we can examine memory addresses using the id() function:

>>> a = b = c = [0, 3, 5]
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261120
>>> id(b[0])
4297261120

>>> a[0] = 1
>>> id(a)
4473392520  # The list object itself remains unchanged
>>> id(b)
4473392520  # Still the same list
>>> id(a[0])
4297261216  # The first element is now a new integer object
>>> id(b[0])
4297261216  # Sharing the same new integer

Multiple Assignment with Immutable Objects

Unlike lists, integers are immutable objects:

d = e = f = 3
e = 4
print('f:', f)  # Output: f: 3
print('e:', e)  # Output: e: 4

The key difference here is that when executing e = 4, we are rebinding the name e to a new integer object 4, not modifying the original integer object 3. Since integers are immutable and cannot be altered, d and f continue to point to the original object 3.

The Nature of Method Calls

From an implementation perspective, a[0] = 1 actually invokes the list object's __setitem__ method, equivalent to a.__setitem__(0, 1). This is not a simple assignment operation but a method call on the object that changes its internal state. This "in-place modification" is characteristic of mutable objects.

Shared Reference Issues in Nested Lists

The 3D list case from the reference article further illustrates this issue:

# Define dimensions
a_dim = 3
b_dim = 5
c_dim = 8

# Create base lists
lst_dim2 = [0] * b_dim
lst_dim3 = [0] * c_dim

# Construct 3D list
lst = [0] * a_dim
for i in range(a_dim):
    lst[i] = lst_dim2
    for j in range(b_dim):
        lst[i][j] = lst_dim3

print(lst)  # Initial state appears normal

lst[1][1][1] = 4  # Modify one element
print(lst)  # Multiple positions unexpectedly modified

The root cause is that in the loop, all lst[i] point to the same lst_dim2 list, and all lst[i][j] point to the same lst_dim3 list. Therefore, modifying lst[1][1][1] actually modifies all positions referencing lst_dim3.

Proper Multiple Assignment and Independent Object Creation

To create truly independent objects, avoid shared references:

# Correct approach: Create independent list objects
a = [0, 3, 5]
b = [0, 3, 5]
c = [0, 3, 5]

# Or use list comprehension
a, b, c = [[0, 3, 5] for _ in range(3)]

# For 3D lists, create independent lists for each position
lst = [[[0 for _ in range(c_dim)] for _ in range(b_dim)] for _ in range(a_dim)]

Summary and Best Practices

Python's multiple assignment mechanism showcases the elegance of its "name-object" model but also introduces pitfalls of shared references. Key takeaways include:

Mastering these concepts is essential for writing correct and efficient Python code, especially when dealing with complex data structures.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.