깊은 복사와 얕은 복사 | Python

이주원·2021년 10월 13일
8

파이썬

목록 보기
2/2

파이썬의 복사엔 두가지 종류가 존재한다는 사실을 알고 계시나요? 파이썬을 사용하다 보면 리스트를 복사해 원본은 그대로 두고 복사본을 따로 수정해 사용하는 경우가 있습니다. 먼저 아래 예제를 보도록 하겠습니다.

>>> a = [1,2,3]
>>> b = a
>>> b[0] = 4
>>> print(a)

과연 결과는 어떻게 나올까요?
직관적으로 생각했을땐 당연히 처음 할당한 값인 [1,2,3]이 나온다고 생각하겠지만, 파이썬에선 다릅니다.

바로 a와 b의 값이 동시에 바뀐것입니다. 이는 바로 파이썬이 순수 객체지향 언어이기 때문입니다. 순수 객체지향 언어에선 모든것을 객체로 취급합니다.
클래스, 함수, 리스트, 심지어 상수마저 어떤 클래스의 객체라고 보는것이죠.
따라서 다음과 같은 코드는

num = 10

변수 num에 10이라는 값을 대입한게 아닌, num이 10이 저장된 객체를 가르키게 하는, C언어의 포인터 연산과 비슷한 동작이 행해지는 것입니다. 이를 얕은 복사라고 합니다.

따라서 위 예제에서 b에 a의 값을 대입한건 값을 복사한게 아닌, [1,2,3]을 가르키는 객체를 할당한 것입니다. 이를 확인해 보기 위해 파이썬의 built-in함수인 id()함수를 사용해보면,

>>> a = [1,2,3]
>>> b = a
>>> id(a)
2810518937664
>>> id(b)
2810518937664

이렇게 똑같은 객체를 가르키고 있는것을 알 수 있습니다.

# 그래서 어떻게 하라고?

이를 위해 파이썬에서 기본제공하는 모듈 copy에서 함수를 제공합니다.
바로 deepcopy()함수이죠. 이를 사용하면 완전한 객체의 복사본을 복사할 수 있습니다.

>>> from copy import deepcopy
>>> a = [1,2,3]
>>> b = deepcopy(a)
>>> id(a)
2810512462400
>>> id(b)
2810512463552

이젠 id값이 서로 다른, 완전히 다른 객체를 가르키고 있다는 것을 알 수 있습니다.

# 그럼 복사를 할 때마다 이걸 써야해?

파이썬엔 변경 가능한 객체(mutable)과 변경 불가능한 객체(immutable)이 있습니다.
변경 가능한 객체엔 리스트, 딕셔너리가 있고, 변경 불가능한 객체엔 일반적인 자료형인 Int, Str ..튜플이 있습니다.

Immutable한 자료형인 튜플, String을 봅시다.

Tuple

>>> a = (1,2)
>>> b = a + (3,)
>>> id(a)
2810518940160
>>> id(b)
2810518862912

String

>>> a = '1'
>>> b = a+'2'
>>> id(a)
2810511826608
>>> id(b)
2810518657008

이처럼 Immutable한 자료형은 변경이 불가능하기 때문에 값이 변하는 순간 가르키는 객체가 변하게 됩니다. 따라서 Immutable한 자료형들은 원본과 같이 바뀔 위험을 생각하지 않아도 된다는 것이죠.

0개의 댓글