코딩하는 임초얀

Story 03. 깊은 복사와 얕은 복사 본문

윤성우의 열혈 파이썬 중급편

Story 03. 깊은 복사와 얕은 복사

초얀 2022. 7. 29. 23:10

이전 글 >> Story 02. 수정 가능한 객체와 수정 불가능한 객체

다음 글 >> Story 04. 리스트 컴프리헨션


두 객체의 비교와 복사

객체의 비교

  • v1 == v2: 변수 v1v2가 참조하는 객체의 내용이 같은가?
  • v1 is v2: 변수 v1v2가 참조하는 객체는 동일 객체인가?

 

is 연산이 True를 반환하는 경우는 다음과 같다.

>>> r1 = [1, 2, 3]
>>> r2 = r1		# r1이 참조하는 리스트에 r2라는 이름을 하나 더 붙임
>>> r1 is r2
True

다음 예제에서 보이는 객체 복사 결과를 살펴보자.

>>> r1 = ['str', ('tu', 'ple'), [1, 2]]
>>> r2 = list(r1)	# r1의 내용으로 새로운 리스트를 만듦
>>> r1 is r2
False
>> r1[0] is r2[0]	# r1과 r2의 'str'은 동일 객체인가?
True
>> r1[1] is r2[1]	# r1과 r2의 ('tu', 'ple')은 동일 객체인가?
True
>> r1[2] is r2[2]	# r1과 r2의 [1, 2]는 동일 객체인가?
True

r1 = ['str', ('tu', 'ple'), [1, 2]]와 같이 리스트를 생성하면 리스트 안에 선언되는 값들이 리스트에 쏙 들어가 있는 형태가 아니라 다음 그림에서 보이듯이 각 값들을(객체들을) 리스트 내에서 참조하는 형태가 된다.

리스트의 객체 참조

 

그리고 r2 = list(r1)과 같이 list 함수를 호출하면서 list를 전달하면 아래와 같이 된다.

리스트의 (얕은) 복사


이러한 형태의 복사를 가리켜 '얕은 복사'라 한다.

'얕은 복사'가 파이썬이 복사를 진행하는 기본 방식이다.

immutable 객체인 문자열 객체와 튜플 객체를 대상으로는 얕은 복사를 진행하는 것이 합리적이다.

하지만 mutable 객체인 리스트 객체를 대상으로 얕은 복사를 하는 것은 문제가 될 수 있다. mutable은 그 안에 담긴 값을 수정할 수 있는 객체이기 때문이다.


깊은 복사

값의 변경이 불가능한 immutable 객체는 얕은 복사를 해도 문제가 되지 않는다.
그러나 값의 변경이 가능한 mutable 객체는 얕은 복사가 문제가 될 수 있다.

mutable 객체에 저장된 값들은 변경될 수 있기 때문에 이들에 대해서는 복사 대상을 하나 더 생성하는 '깊은 복사'를 해야 한다.

 

다음 그림에서 보이듯이 변경 불가능한 'str'('tu', 'ple')은 얕은 복사, 변경 가능한 [1, 2]는 깊은 복사를 진행하는 것이 안전성과 성능을 모두 만족시키는 방법이 된다.

얕은 복사와 깊은 복사


이를 위해서는 copy 모듈의 deepcopy 함수를 사용하면 된다.

import copy
x = copy.copy(y)      # make a shallow copy of y
x = copy.deepcopy(y)  # make a deep copy of y

deepcopy 함수의 호출 결과, immutable 객체를 대상으로는 얕은 복사가 진행되고 mutable 객체를 대상으로는 깊은 복사가 진행된다.


list(), tuple(), str() 등의 함수는 얕은 복사를 진행한다.

Comments