Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Copy vs Reference – copy and deepcopy | Performance Patterns
Python Memory Management

Copy vs Reference – copy and deepcopy

Swipe to show menu

Assigning an object to a new variable does not copy it – both variables point to the same object. Modifying the object through one variable affects the other. Understanding when Python copies and when it references is essential for avoiding unexpected mutations and unnecessary memory duplication.

Assignment Creates References, Not Copies

1234567891011
import sys # Assignment – both variables point to the same object original_budget = {"q1": 50000, "q2": 75000, "q3": 90000} budget_ref = original_budget # No copy – same object budget_ref["q1"] = 99999 # Modifying through budget_ref print(original_budget) # {'q1': 99999, 'q2': 75000, 'q3': 90000} – original changed print(original_budget is budget_ref) # True – same object print(sys.getrefcount(original_budget)) # At least 3

Shallow Copy

A shallow copy creates a new container object but does not copy the objects inside it – nested objects are still shared:

1234567891011121314151617
import copy # Shallow copy – new dict, but nested lists are shared portfolio = { "equities": [150000, 200000, 175000], "bonds": [80000, 95000], } portfolio_shallow = copy.copy(portfolio) portfolio_shallow["equities"].append(250000) # Modifies shared nested list print(portfolio["equities"]) # [150000, 200000, 175000, 250000] – modified! print(portfolio_shallow["equities"]) # [150000, 200000, 175000, 250000] – same object print(portfolio is portfolio_shallow) # False – different dicts print(portfolio["equities"] is portfolio_shallow["equities"]) # True – shared list

For flat structures with no nested mutable objects, shallow copy is sufficient and cheaper.

Deep Copy

copy.deepcopy() recursively copies all nested objects. The result is completely independent:

1234567891011121314
import copy # Deep copy – fully independent copy of nested structure portfolio = { "equities": [150000, 200000, 175000], "bonds": [80000, 95000], } portfolio_deep = copy.deepcopy(portfolio) portfolio_deep["equities"].append(250000) # Only modifies the copy print(portfolio["equities"]) # [150000, 200000, 175000] – unchanged print(portfolio_deep["equities"]) # [150000, 200000, 175000, 250000]

Memory Cost of Deep Copy

Deep copy allocates memory for every nested object. For large structures, this can be expensive:

1234567891011121314151617181920212223
import copy import sys import tracemalloc # Measuring memory cost of deep copy vs shallow copy large_dataset = { f"region_{region_id}": list(range(1000)) for region_id in range(100) } tracemalloc.start() shallow = copy.copy(large_dataset) _, shallow_peak = tracemalloc.get_traced_memory() tracemalloc.clear_traces() deep = copy.deepcopy(large_dataset) _, deep_peak = tracemalloc.get_traced_memory() tracemalloc.stop() print(f"Shallow copy peak: {shallow_peak / 1024:.1f} KB") print(f"Deep copy peak: {deep_peak / 1024:.1f} KB")

Choosing the Right Approach

question mark

What is the key difference between copy.copy() and copy.deepcopy()?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

Section 4. Chapter 2

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

Section 4. Chapter 2
some-alt