Python 튜토리얼: 파이썬에서의 딥/셸로 복사 사용하기
Deep Copy와 Shallow Copy
Python에서 객체를 복사할 때, 대입문은 객체의 복사본을 생성하지 않으며, 객체에 이름을 바인딩(bind)한다. 이는 대부분의 경우(immutalbe 객체의 경우)에는 큰 차이를 만들지 않는다.
하지만 mutable 객체 또는 mutable 객체의 집합과 함께 작업할 때, 이러한 객체의 “진정한 복사본” 또는 “클론”을 생성하는 방법을 찾을 수도 있다. 이 기사에서는 Python 3에서 객체를 복사 또는 “클론”하는 방법을 자세히 설명한다.
유념할 점: 이 튜토리얼은 Python 3를 기준으로 작성되었지만, 객체 복사에 있어 Python 2와 3 사이에는 거의 차이가 없다. 차이가 있는 경우 본문에서 그 차이점을 언급할 것이다.
다만, 이 방법은 사용자 정의 객체에는 작동하지 않으며, 또한 얕은 복사(shallow copy) 만 생성한다는 것을 기억해야 한다. 리스트(list), 딕셔너리(dict), 셋(set)과 같은 복합 객체는 얕은(shallow) 복사와 깊은(deep) 복사 사이에 중요한 차이가 있다.
-
얕은 복사는 새로운 컬렉션 객체를 생성한 다음, 그 원본에서 발견된 자식 객체에 대한 참조(reference)를 채워넣는다. 실제로 얕은 복사는 딱 한 단계까지만 깊게 복사한다. 이 복사 과정은 재귀(recursion)를 행하지 않기 때문에 자식 객체 자체의 복사본을 생성하지 않는다.
-
깊은 복사는 복사 과정을 재귀적으로 수행한다. 즉, 먼저 새로운 컬렉션 객체를 생성한 다음, 원본에서 발견된 자식 객체의 복사본을 재귀적으로 채워넣는다. 이 방법으로 객체를 복사하면 원본 객체와 그 자식 객체들의 전체 객체 트리를 돌면서 원래 객체와 완전히 독립적인 복사본을 만드는 것이다.
이제 얕은 복사와 깊은 복사의 차이를 명확히 하기 위해 몇 가지 예제를 살펴보자.
얕은 복사 만들기
아래 예제에서는 새로운 중첩 리스트를 만들고, list()
팩토리 함수를 사용하여 얕은 복사를 한다.
이렇게 하면 ys
는 xs
와 동일한 내용을 가진 새로운 독립적인 객체가 된다. 이를 확인하기 위해 두 객체를 조사해보자.
실제로 xs
와 ys
는 독립적인 객체임을 확인할 수 있다. 이를 확인하기 위해 작은 실험을 진행해보자. 원본(xs
)에 새로운 서브리스트를 추가한 다음, 이 수정이 복사본(ys
)에 영향을 주지 않는지 확인해본다.
예상한 대로 작동하는 것을 볼 수 있다. 얕은 복사로 원소 리스트의 “외부”수준을 수정하는 것은 전혀 문제가 없다.
하지만 얕은 복사만 수행한 것이기 때문에, ys
는 여전히 원래 자식 객체를 참조하고 있음에 주의하자.