ใน 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 Structure | Deep Copy |
| Immutable Elements (Tuple, String, Int) | Shallow Copy พอ (Immutable ไม่เปลี่ยนได้) |
| Custom Objects | Deep Copy (หรือ Implement __copy__/__deepcopy__) |
| Performance Critical | Shallow + 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