The short answer

A shallow copy makes a new object but reuses the same nested objects, so the copy and the original still share their inner data. A deep copy duplicates everything, including every nested object, so the two are fully independent. The difference only matters when an object holds other mutable objects inside it. In Python, copy.copy() is shallow and copy.deepcopy() is deep.

Shallow copy vs deep copy is a favourite interview question, and a common source of bugs. Both create a new object, so they look the same until you change a nested value. Then a shallow copy surprises you: the change leaks into the original.

The reason is how each one treats the objects inside the object. A shallow copy duplicates only the top level and shares what is nested. A deep copy walks the whole structure and duplicates every level. That single difference decides whether the copy is truly independent.

This guide defines each kind of copy on its own, shows the difference in memory, and gives working code in Python and Java. It also covers when the distinction matters and the interview questions that test it.

Two-panel diagram showing a shallow copy sharing the same nested objects as the original, against a deep copy with its own independent nested objects
A shallow copy shares the nested objects; a deep copy duplicates them, so the two stay independent.

What is a Shallow Copy?

A shallow copy creates a new object and copies the top-level values into it. For any nested object, it copies only the reference, not the nested object itself. So the new object and the original point to the same inner objects.

This means the outer object is independent, but the inner objects are shared. If you change a nested mutable value through one copy, the change shows up in the other. For a flat structure of simple values, that never bites you. For a structure with lists, dictionaries, or other objects inside, it can.

In Python, copy.copy() makes a shallow copy. A list slice a[:], list(a), and a.copy() are shallow too. In Java, the default Object.clone() is a shallow copy.

What is a Deep Copy?

A deep copy creates a new object and then recursively copies every nested object as well. Nothing is shared. The copy is a complete, independent duplicate, all the way down.

Because it rebuilds the whole structure, a deep copy is safe to change without touching the original. The trade-off is cost: it does more work and uses more memory, and it must handle nested references carefully, including cycles where an object refers back to itself.

In Python, copy.deepcopy() makes a deep copy and handles cycles for you. In Java, there is no built-in deep copy; you write it yourself by cloning each nested object, using a copy constructor, or serializing and deserializing the object.

Assignment vs Copy: How It Works

Infographic comparing assignment which shares one object, shallow copy which shares nested objects, and deep copy which duplicates everything, shown as memory boxes and arrows
Assignment shares the whole object; a shallow copy shares only the nested objects; a deep copy shares nothing.

It helps to separate three operations that look similar but differ in memory.

  • Assignment (b = a) copies nothing. Both names refer to the one object, so a change through either is visible through both.
  • Shallow copy makes a new outer object, but its nested fields still point to the original nested objects.
  • Deep copy makes a new outer object and new nested objects, so nothing is shared.

So assignment shares the whole object, a shallow copy shares only the inner objects, and a deep copy shares nothing. Understanding this memory model is closely tied to how a program uses the stack and the heap.

Shallow Copy vs Deep Copy: Key Differences

Comparison infographic listing shallow copy properties such as top-level only, shared nested objects and fast, against deep copy properties such as fully recursive, independent nested objects and slower
Shallow vs deep copy at a glance: what gets copied, whether nested objects are shared, and speed.
AspectShallow CopyDeep Copy
What is copiedThe top-level object onlyThe object and every nested object
Nested objectsShared (same references)Duplicated (independent)
IndependencePartial; inner data is sharedFull; nothing is shared
Side effectsChanging a nested value affects bothChanges never affect the original
SpeedFaster, less memorySlower, more memory
Cyclic referencesNot an issueMust be handled (Python does this)
Pythoncopy.copy(), a[:], a.copy()copy.deepcopy()
JavaDefault Object.clone()Manual: clone each field or serialize
Best whenFlat data, or sharing nested data is fineNested mutable data that must stay separate

Code Examples (Python & Java)

The clearest demo uses a list that contains other lists. The change to a nested list reveals the difference.

Pythoncopy.copy() vs copy.deepcopy():

import copy

original = [[1, 2], [3, 4]]

shallow = copy.copy(original)       # new outer list, SAME inner lists
deep    = copy.deepcopy(original)   # new outer list AND new inner lists

original[0][0] = 99

print(shallow)   # [[99, 2], [3, 4]]  -> inner list is shared, so it changed
print(deep)      # [[1, 2], [3, 4]]   -> fully independent, unaffected

The shallow copy shares the inner lists, so editing original[0][0] also changes shallow. The deep copy rebuilt the inner lists, so it stays the same.

Java — the default clone() is shallow:

class Address { String city; }

class Person implements Cloneable {
    String name;
    Address address;            // nested object

    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();   // SHALLOW: shares the Address
    }
}

Here super.clone() copies the address reference, so the clone and the original share one Address. For a deep copy you also clone the nested Address, for example copy.address = new Address(this.address). The same idea applies in C++ and C#, where the default member-wise copy is shallow and a custom copy constructor makes it deep.

When to Use Shallow Copy vs Deep Copy

Use a shallow copy when the object is flat, or when sharing the nested data is exactly what you want. It is faster and uses less memory, so it suits large structures whose inner parts will not be changed independently.

Use a deep copy when nested mutable objects must stay separate. If you copy an object, edit the copy, and the original must not change, you need a deep copy. Configuration snapshots, undo history, and safe defaults all rely on it.

One rule covers most cases. If every value is immutable, such as numbers, strings, or tuples of those, shallow and deep behave the same. The moment a nested mutable object appears, the choice starts to matter.

Interview Questions on Shallow Copy vs Deep Copy

A shallow copy copies the reference to each nested object, not the object itself. So the copy and the original share the same nested objects. If you change a nested mutable value through one of them, the other sees the change. Only the top-level object is independent.

The default Object.clone() performs a shallow copy. It copies each field value, so primitive fields are duplicated but object fields keep the same reference. To make a deep copy, you override clone() to also clone the nested objects, or you use a copy constructor or serialization.

Use copy.deepcopy(obj) from the copy module. It recursively copies the object and every nested object, and it tracks already-copied objects so cyclic references do not cause infinite loops. copy.copy(obj), by contrast, makes a shallow copy that shares the nested objects.

Frequently Asked Questions

A shallow copy makes a new object but shares the nested objects with the original, so they are only partly independent. A deep copy duplicates the object and every nested object, so the two are fully independent. The difference shows up only when the object contains nested mutable objects.

No. Assignment such as b = a copies no object at all; both names refer to the same single object. A shallow copy creates a new outer object that merely shares the nested objects. So assignment shares everything, while a shallow copy shares only what is nested.

Import the copy module. Use copy.copy(obj) for a shallow copy and copy.deepcopy(obj) for a deep copy. For a simple list, a[:], list(a), and a.copy() also make a shallow copy, while only copy.deepcopy() duplicates nested lists.

It matters only when an object holds nested mutable objects, such as a list of lists or an object with object fields. If every value is immutable, like numbers, strings, or tuples, a shallow copy and a deep copy behave the same. With nested mutable data, only a deep copy keeps the copy fully independent.

Wrapping Up

The whole comparison comes down to nested objects. A shallow copy duplicates the outer object but shares what is inside, while a deep copy duplicates everything and shares nothing. Until a nested mutable object appears, the two look identical.

So ask one question before you copy: will I change the nested data and expect the original to stay the same? If yes, reach for a deep copy. If the data is flat or sharing is fine, a shallow copy is faster and simpler.

Related reading on DiffStudy:


Whatsapp-color Created with Sketch.

By Arun Kumar

Full Stack Developer with a BE in Computer Science, working with React, Next.js, Node.js, MongoDB, and AI/ML tools. Founder of DiffStudy — built to help CS students ace GATE and university exams, and keep developers up to date across AI, cloud, system design, web development, and every field of computer science. Every article is written from real hands-on experience, not just theory.

Leave a Reply

Your email address will not be published. Required fields are marked *


You cannot copy content of this page