Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Shallow Copy vs Deep Copy ใน Python (โมดูล copy)

ใน Python การ Assign (=) ไม่ Copy Object แต่อ้างอิง (Reference) เดียวกัน โมดูล copy ให้ 2 ระดับการ Copy

import copy


Shallow Copy: copy.copy(x)

  • สร้าง Object ใหม่ แต่ อ้างอิง Element เดียวกัน (Level 1 เท่านั้น)
  • Nested Objects ยัง Share Reference
  • เปลี่ยน Nested Element -> ส่งผลต่อ Original

Deep Copy: copy.deepcopy(x)

  • สร้าง Object ใหม่ และ Recursive Copy ทุก Level
  • ไม่ Share Reference ใดๆ กับ Original
  • เปลี่ยน Deep Element -> ไม่ส่งผลต่อ Original

โค้ดตัวอย่าง

import copy

# Nested List (Matrix)
matrix = [[11, 22, 33], [44, 55, 66], [11, 22, 33]]
print("Original:", matrix)

# Shallow Copy
shallow = copy.copy(matrix)
shallow[2][0] = 77
shallow[2][1] = 88
shallow[2][2] = 99

print("After Shallow Modify:")
print("  Original:", matrix)      # เปลี่ยนไปด้วย!
print("  Shallow: ", shallow)

# Deep Copy
matrix = [[11, 22, 33], [44, 55, 66], [11, 22, 33]]
deep = copy.deepcopy(matrix)
deep[2][0] = 77
deep[2][1] = 88
deep[2][2] = 99

print("\nAfter Deep Modify:")
print("  Original:", matrix)      # ไม่เปลี่ยน
print("  Deep:    ", deep)        # เปลี่ยนเฉพาะ Copy

ผลลัพธ์

Original: [[11, 22, 33], [44, 55, 66], [11, 22, 33]]
After Shallow Modify:
  Original: [[11, 22, 33], [44, 55, 66], [77, 88, 99]]  # เปลี่ยน!
  Shallow:  [[11, 22, 33], [44, 55, 66], [77, 88, 99]]

After Deep Modify:
  Original: [[11, 22, 33], [44, 55, 66], [11, 22, 33]]  # คงเดิม
  Deep:     [[11, 22, 33], [44, 55, 66], [77, 88, 99]]

เมื่อไหร่ใช้แบบไหน?

สถานการณ์แนะนำ
Flat List/Dict (ไม่มี Nested)Shallow Copy พอ (เร็วกว่า)
Nested StructureDeep Copy
Immutable Elements (Tuple, String, Int)Shallow Copy พอ (Immutable ไม่เปลี่ยนได้)
Custom ObjectsDeep Copy (หรือ Implement __copy__/__deepcopy__)
Performance CriticalShallow + Manual Deep Copy เฉพาะที่ต้องการ

Custom Copy Behavior

import copy

class MyClass:
    def __init__(self, data):
        self.data = data
    
    def __copy__(self):
        # Shallow Copy Custom
        return MyClass(self.data)
    
    def __deepcopy__(self, memo):
        # Deep Copy Custom
        return MyClass(copy.deepcopy(self.data, memo))

obj = MyClass([1, [2, 3]])
shallow = copy.copy(obj)
deep = copy.deepcopy(obj)

Alternative: List/Dict Copy Methods

# Shallow Copy Alternatives
lst = [1, 2, [3, 4]]
lst_copy1 = lst.copy()           # List Method
lst_copy2 = lst[:]               # Slice
lst_copy3 = list(lst)            # Constructor
lst_copy4 = copy.copy(lst)       # Copy Module

# Deep Copy Alternative (List Only)
import json
deep_lst = json.loads(json.dumps(lst))  # Hack: Serialize + Deserialize

Performance

import timeit

nested = [[i] * 100 for i in range(100)]

print("Shallow:", timeit.timeit(lambda: copy.copy(nested), number=10000))
print("Deep:   ", timeit.timeit(lambda: copy.deepcopy(nested), number=10000))
# Shallow ~100x Faster