본문 바로가기
Programming/Python

깊은 복사와 얕은 복사

by DUSTIN KANG 2024. 4. 8.

오늘 면접을 보면서 제대로 기억하지 못한 파이썬의 깊은 복사와 얕은 복사에 대해 포스팅하려고 합니다.

 

  • 얕은 복사(Shallow Copy) : 참조를 입력하는 복사, 변수명은 다르지만 서로 같은 대상이다.
    • immutable한 객체는 변경이 불가능하기 때문에 변수를 바꿔야 객체가 달라진다.
  • 깊은 복사(Deep Copy) :  서로 값만 같을 뿐, 본질적으로는 서로 다르기 때문에 수정시, 다른 변수가 수정되지 않는다.

 

🌱 mutable, immutable 객체, 변하다..변하지 않다.

먼저, 깊은 복사와 얕은 복사에 대해 알기 전에 파이썬의 두가지 객체인 Mutable한 객체와 Immutable한 객체에 대해 알필요가 있습니다.

  • Mutable : 객체의 상태를 변경할 수 있는 객체입니다. list, set, dict
  • immutable : 변경이 되지 않은 객체로 객체의 상태를 변경할 수 없습니다. int, float, tuple,str, bool

객체의 상태가 변경되지 않는다는 말을 어떻게 알 수 있을까요?

아래 세가지 예시를 통해 알아봅시다.

 

위 그림을 보면, int나 str의 경우 참조되는 변수가 변경되어도 메모리 주소값이 변경되지 않습니다.

반면, 리스트나 딕셔너리와 같은 immutable한 형태는 값이 변경되면 메모리 주소가 달라집니다.

그렇다면 여기서 리스트 내에 있는 mutable한 객체들은 어떻게 될까요? 역시나 mutable한 객체는 참조하는 값이 동일하면 메모리 주소가 달라지지 않습니다. 또, 리스트 내 새로운 값을 추가한다고 하더라도 메모리 주소는 달라지지 않습니다.


☘️ 얕은 복사(Shallow Copy)

이번 포스팅에서는 값을 대입하는 경우, 얕은 복사의 경우, 깊은 복사의 경우를 다루면서 차이를 알아보려고 합니다.

먼저, 값을 얕은 복사하게 되면 메모리 주소가 바뀌는지 알아봅시다. 얕은 복사는 다음 코드로 복사할 수 있습니다.

  • =
  • copy()
  • [:]
  • copy.copy

얕은 복사

여기서 중요한 부분이 있습니다.

`a = b`로 얕은 복사를 했을 경우와 `b = a.copy()`를 했을 때 다른 메모리 주소가 나온다는 것입니다.

그럼, 얕은 복사가 아닌건가 하실 수 있습니다. 하지만 내부적으로 보면 얕은 복사인 것을 아실 수 있습니다.

예를 들어 다음과 같은 딕셔너리 객체를 얕은 복사한다고 가정해봅시다.

a = {'korea' : [[1,2], [3,4]]}
b = a.copy() # 얕은 복사 ([:], copy.copy(a))

print(id(a) == id(b)) # False
print(id(a['korea']) == id(b['korea'])) # True
print(id(a['korea'][0]) == id(b['korea'][0])) # True

 

깊은 복사인 줄 알았지만 내부적으로 보면 얕은 복사인 것을 알 수 있습니다. 

즉, 외부의 리스트는 새로운 객체를 추가했으나 내부 요소들은 같은 리스트를 가리키고 있음을 확인할 수 있습니다.

[:], copy()일때 얕은 복사

더보기
  • `is` : 객체 비교 연산자로 두 변수의 id를 비교하는 연산자입니다. 
  • `not` : 단항 논리 연산자로 뒤에 오는 boolean 값을 뒤집는 연산자입니다.
  • `in` : 맴버 연산자로 요소 a가 시퀀스 b에 있는지 확인하는 연산자입니다.

☘️ 깊은 복사(Deep Copy)

이번엔 깊은 복사를 사용하기위해 deepcopy를 사용하는 예시입니다.

깊은 복사는 리스트의 내부 리스트 모두 새롭게 복사하는 것을 말합니다. 그러니까 독립 선언한다는 것이죠.

 

이때 이전 얕은 복사와 달라지는 것은 immutable 객체 내 immutable 객체의 주소값이 변한 다는 것입니다.

import copy

a = [1,2,[3,4]]
b = copy.deepcopy(a)

print(id(a) == id(b)) # False
print(id(a[0]) == id(b[0])) # True
print(id(a[2]) == id(b[2])) # False

 

DeepCopy

 


☕️ 포스팅이 도움이 되었던 자료

오늘도 저의 포스트를 읽어주셔서 감사합니다.

설명이 부족하거나 이해하기 어렵거나 잘못된 부분이 있으면 부담없이 댓글로 남겨주시면 감사하겠습니다.