본문 바로가기

Programming/Python

파이썬 데이터 깊은 복사(Deep Copy)와 얕은 복사(Swallow Copy)

반응형

데이터를 복사할 때 깊은 복사(Deep Copy)얕은 복사(Swallow Copy)가 존재합니다.

C++에서는 포인터 등의 얕은 복사는 여러 문제를 야기하는 요인 중 하나입니다.

C++에서 힙에 생성한 메모리를 해제된 이후에 다른 변수에서 참조하면 문제가 발생하게 됩니다.

깊은 복사와 얕은 복사의 메모리 개념은 아래의 포스팅의 이미지를 참조하면 됩니다.

2015/01/14 - [Programming/C&C++] - 얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy)

앝은 복사는 다른 변수가 동일한 메모리를 가리키게 됩니다.

파이썬에서 리스트를 대입해서 생성하는 경우 얕은 복사가 발생하게 됩니다.

myList1 = [1, 2, 3, 4]
myList2 = myList1

print(hex(id(myList1)))
print(hex(id(myList2)))

myList1[2] = 100

print(myList1[2])
print(myList2[2])

두 변수의 주소가 동일하게 출력되는 것을 확인할 수 있습니다.

myList1의 세 번째 값을 변경하면 myList2의 세 번째 값 역시 영향을 받게 됩니다.

파이썬에서는 추가적으로 다음과 같은 복사 방법을 제공합니다.

myList1 = [1, 2, 3, 4]
myList2 = myList1.copy()
myList3 = myList1[:]
myList4 = list(myList1)

print(hex(id(myList1)))
print(hex(id(myList2)))
print(hex(id(myList3)))
print(hex(id(myList4)))

myList1[2] = 100
myList2[2] = 101
myList3[2] = 102
myList4[2] = 103

print(myList1[2])
print(myList2[2])
print(myList3[2])
print(myList4[2])

파이썬 list의 메소드 중 하나인 copy()로 깊은 복사를 실행할 수 있습니다.

그리고 슬라이싱list() 생성자를 통해서 생성을 할 수 있습니다.

각각의 리스트가 전부 다른 주소를 가리키며 각각의 요소를 변경해도 영향을 받지 않습니다.

이렇게 모든 것이 완벽하면 좋겠지만 list 안에 list가 포함된 중첩된 구조에서 문제가 발생합니다.

myList1 = [1, 2, [3, 4], 5]
myList2 = myList1.copy()

print(hex(id(myList1)))
print(hex(id(myList2)))
print(hex(id(myList1[2])))
print(hex(id(myList2[2])))

리스트 자체의 주소는 다르지만 내부의 [3, 4]의 주소는 동일하게 출력됩니다.

list 안의 list는 정상적인 깊은 복사가 발생하지 않은 것입니다.

그래서 파이썬의 copy에는 deepcopy()라는 메소드가 지원됩니다.

deepcopy를 사용하기 위해서는 copy 라이브러리를 먼저 import하고 사용할 수 있습니다.

import copy

myList1 = [1, 2, [3, 4], 5]
myList2 = copy.deepcopy(myList1)

print(hex(id(myList1)))
print(hex(id(myList2)))
print(hex(id(myList1[2])))
print(hex(id(myList2[2])))

deepcopy()를 사용해서 파이썬의 깊은 복사를 사용할 수 있습니다.

반응형