Python
object copying
deepcopy
shallow copy
Python programming

How can I create a copy of an object in Python?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Creating a copy of an object in Python is not one single operation. The right technique depends on whether you want a new reference, a shallow copy, or a deep copy of nested state. The key distinction is simple: shallow copies duplicate the outer container, while deep copies recursively duplicate the contained objects as well.

Assignment Is Not Copying

The assignment operator binds another name to the same object. It does not create a new one.

python
1original = [1, 2, 3]
2alias = original
3
4alias.append(4)
5print(original)
6print(alias)

Both variables refer to the same list, so the mutation is visible through both names.

This is the first thing to check when someone says "my copy changed too." In many cases there was never a copy at all.

Shallow Copy

A shallow copy creates a new outer object but keeps references to the same nested objects inside it.

python
1import copy
2
3original = [[1, 2], [3, 4]]
4shallow = copy.copy(original)
5
6shallow.append([5, 6])
7shallow[0].append(99)
8
9print(original)
10print(shallow)

Appending a new top-level element affects only shallow, because the outer list is different. But modifying shallow[0] affects both, because the nested inner list is shared.

Built-in containers also have common shallow-copy shortcuts:

python
numbers = [1, 2, 3]
a = numbers.copy()
b = numbers[:]

Those are still shallow copies.

Deep Copy

A deep copy recursively copies nested objects too.

python
1import copy
2
3original = [[1, 2], [3, 4]]
4deep = copy.deepcopy(original)
5
6deep[0].append(99)
7print(original)
8print(deep)

Now the nested lists are independent, so changing one does not affect the other.

Use deep copy when you truly need a separate object graph. Do not use it automatically everywhere, because it can be expensive and may copy much more than you intend.

Choosing Between Shallow and Deep Copy

A shallow copy is usually enough when:

  • the object contains only immutable values
  • you want a new container but shared members are acceptable
  • you know nested state will not be mutated

A deep copy is more appropriate when:

  • nested mutable objects must be independent
  • you are cloning configuration or state for isolated modification
  • the object graph is small enough that recursive copying is acceptable

The correct choice is about ownership of nested state, not just about syntax.

Copying Custom Objects

For user-defined classes, copy.copy() and copy.deepcopy() work on instance attributes, but sometimes the default behavior is not what you want. In that case, implement __copy__ and __deepcopy__.

python
1import copy
2
3class UserProfile:
4    def __init__(self, name, settings):
5        self.name = name
6        self.settings = settings
7
8    def __copy__(self):
9        return UserProfile(self.name, self.settings)
10
11    def __deepcopy__(self, memo):
12        return UserProfile(
13            copy.deepcopy(self.name, memo),
14            copy.deepcopy(self.settings, memo),
15        )
16
17original = UserProfile("Ada", {"theme": {"mode": "dark"}})
18clone = copy.deepcopy(original)
19clone.settings["theme"]["mode"] = "light"
20
21print(original.settings)
22print(clone.settings)

This gives you explicit control over which parts should be shared and which parts should be duplicated.

Dataclasses and Immutable Design

Sometimes the best answer is to avoid mutable shared state instead of copying it heavily. For dataclasses, dataclasses.replace can be clearer when you want a modified copy of a mostly immutable object.

python
1from dataclasses import dataclass, replace
2
3@dataclass(frozen=True)
4class Point:
5    x: int
6    y: int
7
8p1 = Point(2, 3)
9p2 = replace(p1, y=10)
10
11print(p1)
12print(p2)

That is often a better design than performing deep copies of complex mutable objects.

Common Pitfalls

The most common mistake is confusing assignment with copying. A second variable name is not a duplicate object.

Another issue is using a shallow copy when nested mutable objects need to be independent. The outer container changes correctly, but inner objects still leak mutations.

Developers also sometimes reach for deepcopy too early. Deep copying large object graphs can be slow and may duplicate resources or state that should not be cloned blindly.

Finally, if a class manages external resources such as files, sockets, or locks, copying semantics may need careful design rather than a default generic copy.

Summary

  • Assignment creates another reference, not a copy.
  • Use shallow copy when you need a new outer object but can share nested members.
  • Use deep copy when nested mutable state must be independent.
  • Implement __copy__ and __deepcopy__ for custom copy behavior when needed.
  • Prefer clearer immutable designs when copying complex mutable state becomes awkward.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.