객체 지향 프로그래밍/Python

얕은 복사, 깊은 복사란?

ghtis1798 2021. 3. 11. 13:33

복사는 복사인데 얕은 것과 깊은 것의 차이는 무엇일까?

핵심은 값의 복사이냐 주소값의 복사이냐의 차이이다.

C에서는 포인터 개념이 존재하므로 언어 학습 시 꼭 배우게 되는 개념이다.

Call by ReferenceCall by Value이냐를 갖고 고민했던 기억이 난다.

파이썬에서는 얕은 복사가 Call by Reference, 깊은 복사가 Call by Value이다.

📌얕은 복사 = 주소값 복사

# Python
list_1= [1,2,3]
list_2 = list_1

# list_1과 list_2가 참조하는 대상(객체)이 같습니까?
if list_1 is list_2:
    print('list_1과 list_2는 같은 객체를 참조합니다.')

# list_1과 list_2가 참조하는 대상에 담긴 값이 같습니까?
if list_1 == list_2:
    print('list_1과 list_2가 참조하는 객체에 담긴 값이 같습니다.')

현재 리스트는 [1,2,3] 딱 1개만 존재한다.

[1,2,3] 리스트 하나를 list_1 변수와 list_2 변수가 참조하고 있는 형태이다.

따라서 이 list [1,2,3]의 레퍼런스 카운터는 2이다.

하나 더 알 수 있는 것이 있다.

'=='는 참조하는 대상에 담긴 값이 같느냐를 확인한다.

'is'는 참조하는 대상이 같냐를 확인한다는 것을 알 수 있다.

list_1 = 'Skinny Brown'

list_1 변수가 'Skinny Brown'을 참조하도록 변경했다.

[1,2,3] 리스트의 레퍼런스 카운트는 1이다.

동시에 'Skinny Brown'이라는 문자열의 레퍼런스 카운트는 1이 된다.

여기서 list_2 변수가 다른 객체를 참조하도록 변경하면 어떻게 될까?

리스트 [1,2,3]은 가비지 컬렉터가 메모리 공간을 수거해간다.

📌깊은 복사 = 값 복사

깊은 복사는 아예 값 자체를 복사해 버리는 것이다.

파이썬은 기본적으로 얕은 복사를 수행한다.

위에서도 list_1 = list_2를 수행했을 때 얕은 복사가 진행되었다.

깊은 복사를 수행하려면 copy함수의 deepcopy()함수를 사용해야한다.

그럼 리스트 안에 ['Skinny Brown', ('GH', 32), [1,2,3]] 처럼 여러 자료형이 섞여 있을 경우 어떨까?

list_3 = ['Skinny Brown', ('GH', 32), [1,2,3]]
list_4 = copy.deepcopy(list_3)

문자열 Skinny Brown과 튜플 ('GH', 32)은 변경이 불가능한 immutable 객체이다.

반면 [1,2,3]은 리스트로 변경 가능한 mutable 객체이다.

이 때 깊은 복사를 진행하게 되면 immutable 객체는 얕은 복사를, mutable 객체는 깊은 복사를 수행하게 된다.