복사는 복사인데 얕은 것과 깊은 것의 차이는 무엇일까?
핵심은 값의 복사이냐 주소값의 복사이냐의 차이이다.
C에서는 포인터 개념이 존재하므로 언어 학습 시 꼭 배우게 되는 개념이다.
Call by Reference냐 Call 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 객체는 깊은 복사를 수행하게 된다.
'객체 지향 프로그래밍 > Python' 카테고리의 다른 글
파이썬에서는 모든 것이 객체! (2) | 2021.03.14 |
---|---|
리스트 컴프리헨션으로 가독성 높이기 (0) | 2021.03.13 |
변경 불가능한 자료형 주의하기 (0) | 2021.03.10 |
파이썬은 정말 인터프리터 언어일까? (1) | 2021.03.10 |
파이썬 변수는 언제 소멸될까? (2) | 2021.03.10 |