ZetCode

Python Copy by Value vs Copy by Reference

last modified May 16, 2025

This tutorial explains how Python handles mutable and immutable types, affecting variable assignment and parameter passing. Understanding these concepts is crucial for writing correct and efficient Python code.

Mutable vs Immutable Types

Python types are categorized as mutable or immutable, which determines how data is copied and shared between variables.

Characteristic Immutable Types Mutable Types
Modifiable No (new object created) Yes (in-place changes)
Copy Behavior Effectively by value By reference
Examples int, str, tuple list, dict, set

Assignment with immutable types creates independent copies, while mutable types share references. However, Python always passes references - the difference is whether the object can be modified in-place.

Immutable Types Example

Immutable types appear to create independent copies when assigned, because modification creates a new object rather than changing the existing one.

main.py
a = 10
b = a  # Both reference the same object

print(f"Original: a = {a}, b = {b}")
b = 20  # Creates new object, doesn't affect a
print(f"After change: a = {a}, b = {b}")

# Strings are also immutable
s1 = "hello"
s2 = s1
s2 = "world"  # Doesn't affect s1
print(f"s1 = {s1}, s2 = {s2}")

The example shows that modifying an immutable type creates a new object, leaving the original unchanged. The output will be:

$ python main.py
Original: a = 10, b = 10
After change: a = 10, b = 20
s1 = hello, s2 = world

Mutable Types Example

Mutable types share references when assigned, so changes to one variable affect all references to the same object.

main.py
vals1 = [1, 2, 3]
vals2 = vals1  # Both reference the same list

print(f"Original: vals1 = {vals1}, vals2 = {vals2}")
vals2[0] = 99  # Modifies the shared list
print(f"After change: vals1 = {vals1}, vals2 = {vals2}")

# Dictionaries behave the same way
dict1 = {'a': 1}
dict2 = dict1
dict2['a'] = 100  # Affects both references
print(f"dict1 = {dict1}, dict2 = {dict2}")

This demonstrates that mutable types share references. The output shows changes to one variable affect the other:

$ python main.py
Original: vals1 = [1, 2, 3], vals2 = [1, 2, 3]
After change: vals1 = [99, 2, 3], vals2 = [99, 2, 3]
dict1 = {'a': 100}, dict2 = {'a': 100}

Creating True Copies

To create independent copies of mutable objects, use the copy module or sequence-specific methods:

main.py
import copy

# Shallow copy example
original = [1, [2, 3], 4]
shallow_copy = copy.copy(original)

shallow_copy[0] = 10  # Doesn't affect original
shallow_copy[1][0] = 20  # Affects nested object in original

print(f"Original: {original}")
print(f"Shallow copy: {shallow_copy}")

# Deep copy example
deep_copy = copy.deepcopy(original)
deep_copy[1][0] = 30  # Doesn't affect original

print(f"Original: {original}")
print(f"Deep copy: {deep_copy}")

Shallow copies create new containers but share references to nested objects. Deep copies recursively copy all objects. The output demonstrates the difference:

$ python main.py
Original: [1, [20, 3], 4]
Shallow copy: [10, [20, 3], 4]
Original: [1, [20, 3], 4]
Deep copy: [1, [30, 3], 4]

Parameter Passing

Python always passes arguments by object reference. For immutable objects, this behaves like pass-by-value since they can't be modified. For mutable objects, functions can modify the original object.

main.py
def modify_list(lst):
    lst.append(4)  # Modifies the original list
    
def modify_number(num):
    num += 10  # Creates new object, doesn't modify original

numbers = [1, 2, 3]
modify_list(numbers)
print(f"List after modification: {numbers}")

x = 5
modify_number(x)
print(f"Number after modification: {x}")

The list is modified in-place, while the number remains unchanged:

$ python main.py
List after modification: [1, 2, 3, 4]
Number after modification: 5

Summary and Best Practices

Understanding Python's object model helps prevent bugs and write efficient code when working with complex data structures.

In this tutorial, we explored the differences between mutable and immutable types in Python, focusing on how they affect variable assignment and parameter passing. We learned that immutable types create independent copies when assigned, while mutable types share references. This understanding is crucial for writing correct and efficient Python code. We also discussed how to create true copies of mutable objects using the copy module and the importance of understanding parameter passing in Python.

Source

Python standard types

Python copy module

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.