杰瑞科技汇

Python中copy与deepCopy有何本质区别?

Of course! This is a fundamental and important concept in Python. Let's break down copy and deepcopy with clear explanations, examples, and when to use each.

The Core Problem: Shallow vs. Deep Copying

In Python, variables are essentially references (or pointers) to objects in memory. When you assign a variable to another, you're not creating a copy of the object; you're creating a new reference to the same object.

Python中copy与deepCopy有何本质区别?-图1

# Let's create a list
my_list = [1, 2, 3]
print(f"Original list: {my_list}")
print(f"ID of original list: {id(my_list)}")
# Now, assign it to a new variable
new_list = my_list
print(f"New list: {new_list}")
print(f"ID of new list: {id(new_list)}") # Same ID!
# Modify the new list
new_list.append(4)
# See what happens to the original list
print(f"After modifying new_list, original list is: {my_list}")
# Output: After modifying new_list, original list is: [1, 2, 3, 4]

Both my_list and new_list point to the exact same list object in memory. Modifying one affects the other. This is often not what we want.

This is where the copy module comes in. It provides two ways to create copies: shallow copy and deep copy.


Shallow Copy (copy.copy())

A shallow copy creates a new object but populates it with references to the objects found in the original.

Think of it like getting a new moving box. The box itself is new, but if you put books inside it, you're just putting the same books (the references) into the new box. You haven't created new copies of the books.

How to Create a Shallow Copy:

  • copy.copy(object)
  • For sequences (like lists), you can also use the slice notation: my_list[:]
  • The list() or dict() constructors also create shallow copies.

Example 1: Simple List of Integers

import copy
original_list = [1, 2, 3]
shallow_copied_list = copy.copy(original_list)
print(f"Original: {original_list} (ID: {id(original_list)})")
print(f"Copy:     {shallow_copied_list} (ID: {id(shallow_copied_list)})")
# Modify the copy
shallow_copied_list.append(4)
print("\nAfter modifying the copy:")
print(f"Original: {original_list}") # Unchanged
print(f"Copy:     {shallow_copied_list}") # Changed

Output:

Python中copy与deepCopy有何本质区别?-图2

Original: [1, 2, 3] (ID: 140123456789)
Copy:     [1, 2, 3] (ID: 140123456900)
After modifying the copy:
Original: [1, 2, 3]
Copy:     [1, 2, 3, 4]

As you can see, the lists are now two separate objects in memory. Modifying the top-level list does not affect the other.

Example 2: The "Gotcha" with Nested Objects

This is where shallow copy's behavior can be surprising. If your list contains other mutable objects (like other lists, dictionaries, or sets), the shallow copy will only copy the references to those inner objects.

import copy
original_list = [1, [2, 3], 4]
shallow_copied_list = copy.copy(original_list)
print(f"Original: {original_list}")
print(f"Copy:     {shallow_copied_list}")
# Modify an element in the original list's nested list
original_list[1].append(99) # This modifies the list at index 1
print("\nAfter modifying the nested list in the original:")
print(f"Original: {original_list}")
print(f"Copy:     {shallow_copied_list}")

Output:

Original: [1, [2, 3], 4]
Copy:     [1, [2, 3], 4]
After modifying the nested list in the original:
Original: [1, [2, 3, 99], 4]
Copy:     [1, [2, 3, 99], 4]

Why? Because the shallow copy created a new outer list, but the element at index 1 in both the original and the copy is a reference to the exact same inner list [2, 3]. So when you modify that inner list through one reference, you see the change through the other.


Deep Copy (copy.deepcopy())

A deep copy creates a new object and recursively creates copies of all objects found within the original.

Python中copy与deepCopy有何本质区别?-图3

Think of it like getting a new moving box and then photocopying every single book, CD, and photo before putting them in the new box. Nothing is shared between the original and the copy.

How to Create a Deep Copy:

  • copy.deepcopy(object)

Example: The Solution to the "Gotcha"

Let's use the exact same scenario as before, but with a deep copy.

import copy
original_list = [1, [2, 3], 4]
deep_copied_list = copy.deepcopy(original_list)
print(f"Original: {original_list}")
print(f"Copy:     {deep_copied_list}")
# Modify an element in the original list's nested list
original_list[1].append(99)
print("\nAfter modifying the nested list in the original:")
print(f"Original: {original_list}")
print(f"Copy:     {deep_copied_list}")

Output:

Original: [1, [2, 3], 4]
Copy:     [1, [2, 3], 4]
After modifying the nested list in the original:
Original: [1, [2, 3, 99], 4]
Copy:     [1, [2, 3], 4]

Now, the copy is completely independent. The change to the nested list in the original has no effect on the deep-copied list. This is because deepcopy created a brand new inner list [2, 3] for the copy.


Summary Table: Shallow vs. Deep Copy

Feature Shallow Copy (copy.copy()) Deep Copy (copy.deepcopy())
Top-Level Object Creates a new object. Creates a new object.
Nested Objects Copies references to nested objects. Recursively creates new copies of all nested objects.
Performance Faster and uses less memory. Slower and uses more memory (due to recursive copying).
Use Case When your object is flat (no nested mutable objects) or when you intentionally want to share nested objects. When you need a fully independent clone of an object and its children.
Example new_list = old_list[:] or copy.copy(old_list) new_list = copy.deepcopy(old_list)

When to Use Which?

Use a Shallow Copy when:

  1. You have simple, immutable data. If your list only contains numbers, strings, or tuples, a shallow copy is sufficient and efficient.
    my_list = [1, "hello", (3, 4)]
    new_list = my_list[:] # Perfectly fine
  2. You want to share nested objects. This is less common but can be useful in specific scenarios where you want to create a new container but have it refer to the same sub-objects.
  3. Performance is critical. If you're working with very large objects and a shallow copy is enough, it will be faster.

Use a Deep Copy when:

  1. You need a completely independent clone. This is the most common reason. You want to make changes to the copy without any risk of affecting the original object, no matter how deeply nested those changes are.
  2. You are working with complex data structures. This includes lists of lists, dictionaries of dictionaries, or any combination of mutable objects.
  3. You are serializing/deserializing objects. For example, when you want to send a copy of an object over a network or save it to a file without the original being affected by subsequent changes.

Performance Warning

Deep copying can be very slow and memory-intensive, especially for large and complex objects. It's a recursive process that can lead to infinite loops if an object refers to itself (circular references). However, copy.deepcopy is smart enough to handle most circular references correctly.

Example of a circular reference:

a = [1, 2, 3]
a.append(a) # a now contains a reference to itself
b = copy.deepcopy(a) # deepcopy handles this

分享:
扫描分享到社交APP
上一篇
下一篇