본문 바로가기
Python/파이썬 기초

얕은복사(Shallow copy)와 깊은복사(Deep copy), copy모듈 - 파이썬 기초(28)

by 콩돌 2019. 3. 10.
반응형

참고 자료

https://docs.scipy.org/doc/numpy/user/quickstart.html

https://docs.python.org/3/library/copy.html

https://wikidocs.net/16038


파이썬 버전 3.7 기준

NumPy 버전 1.16 기준


본 포스팅에서는 얕은 복사(Shallow copy)와 깊은 복사(Deep copy), copy 모듈에 대해 다룬다.



얕은 복사(Shallow copy)와 깊은 복사(Deep copy) 


파이썬에서는 얕은 복사와 깊은 복사라는 것이 존재하며 이를 지원하기 위해 copy모듈이 존재한다. 

copy 라이브러리

  ○ 파이썬에서는 얕은 복사와 깊은 복사를 수행하기 위해서 표준라이브러리에서 copy 라이브러리를 제공한다.

  ○ 이 라이브러리는 모듈, 메서드, 스텍트레이스, 스텍프레임, 파일, 소켓, 윈도우, 배열, 혹은 유사한 타입들에 대해서는 복사를 수행하지 않는다. 


copy.copy(x)

  ○ 입력되는 변수 x의 얕은 복사를 반환한다.


copy.deepcopy(x[, memo])

  ○ 입력되는 변수 x의 깊은 복사를 반환한다.


exception copy.error

  ○ 이 모듈을 사용할 때 오류가 발생할 경우에 일어나는 예외이다.

 

얕은 복사(Shellow copy)의 개념

  ○ 얕은 복사는 새로운 객체(변수)를 만든 후에 원본에 접근할 수 있는 참조(reference)를 입력한다.

    ▷ 이런 경우 서로 다른 변수명이지만 본질적으로 서로 같은 대상을 의미하므로 하나의 변수를 수정하면 다른 변수 역시 수정이 된다.

  ○ 가변형(mutable) 자료형에 대해서 적용이 가능하다. 

    ▷ 가변형(mutable) 자료형은 같은 주소에서 값(value)이 변경 가능하기 때문에 얕은 복사가 적용 가능하다.

    ▷ 불변형(immutable) 자료형은 본질적으로 변경이 불가능하므로 재배정을 통해 변수를 바꾼다. 따라서 재배정이 이루어지므로 객체가 서로 달라진다.

 

깊은 복사(Deep copy)의 개념

  ○ 깊은 복사는 새로운 객체(변수)를 만든 뒤에 원본의 복사본을 변수에 입력한다.

    ▷ 서로 값만 같을 뿐 본질적으로 서로 다르기 때문에 한 변수가 수정될 시 다른 변수가 수정되지 않는다. 

얕은 복사, 깊은 복사의  예제

  ○ 다음 예제는 얕은 복사와 깊은 복사를 수행한 예제이다.

  ○ 불변형(immutable) 자료형을 변경했을 경우에는 재배정이 이루어지기 때문에 얕은복사와 깊은 복사 모두 변경되지 않는다.

  ○ 가변형(mutable) 자료형을 변경했을 경우에는 얕은 복사에서는 같이 변경되나 깊은 복사에서는 변경되지 않는다.

  ○ 가변형 자료형 안에 불변형 자료형을 변경하였을 경우에는 얕은 복사에서는 같이 변경되고 깊은 복사에서는 변경되지 않는다.
    ▷ 이 부분이 주의해야할 사항인데 copy.copy() 함수는 a만을 복사를 수행한거고 각각의 요소에 대해서는 배정을 수행한 것으로 추측된다. (배정에 대해서는 아래에 예제를 통해 다시 다룬다.)

얕은 복사와 깊은 복사의 예)
# 예제용 입력
In[2]: import copy
In[3]: a = [1,2,[4,5,6]]
In[4]: b = copy.copy(a)                 # 얕은 복사
In[5]: c = copy.deepcopy(a)           # 깊은 복사

# 불변형(immutable) 자료의 변경
In[6]: a[0] = 100 
In[7]: a
Out[7]: [100, 2, [4, 5, 6]]
In[8]: b
Out[8]: [1, 2, [4, 5, 6]]
In[9]: c
Out[9]: [1, 2, [4, 5, 6]]

# 가변형(mutable) 자료의 변경
In[10]: a[2].append(7)
In[11]: a
Out[11]: [100, 2, [4, 5, 6, 7]]
In[12]: b
Out[12]: [1, 2, [4, 5, 6, 7]]
In[13]: c
Out[13]: [1, 2, [4, 5, 6]]

# 가변형 자료 안의 불변형 자료의 변경
In[14]: a[2][1] = 400
In[15]: a
Out[15]: [100, 2, [4, 400, 6, 7]]
In[16]: b
Out[16]: [1, 2, [4, 400, 6, 7]]
In[17]: c
Out[17]: [1, 2, [4, 5, 6]]


배정 구문(Assignment statement)의 사용

  ○ 배정 구문을 사용하는 것은 복사본을 만든다는 것과는 개념이 다르다.

    ▷ 배정 구문은 엄밀히 말하면 복사본을 만드는 것이 아니라, 타겟과 오브젝트를 엮는 역할을 한다라는 표현이 좀 더 옳다.

    ▷ 그래도 거동이 비슷한 부분이 있고, 이 부분을 잘못사용하면 큰 문제를 야기할 수도 있으므로 다음 예제를 통해 소개한다.

배정구문 예 1)

# 예제용 입력

In[23]: a = [9,9,9,9]

In[24]: b = a            # 배정


# 각 변수의 주소 출력 및 같은 객체임을 확인

In[25]: print('a id : ', id(a), '\nb id : ', id(b))

a id :  72339048 

b id :  72339048

In[26]: a is b

Out[26]: True


# 변수 하나를 변경시 다른 변수에서 변경됨을 확인 

In[27]: a[3] = 101

In[28]: a

Out[28]: [9, 9, 9, 101]

In[29]: b

Out[29]: [9, 9, 9, 101]


In[30]: b.append(90)

In[31]: a

Out[31]: [9, 9, 9, 101, 90]

In[32]: b

Out[32]: [9, 9, 9, 101, 90]


# 재배정을 수행하는 경우 서로 다른 객체가 됨

In[33]: a = [10,10,10,10]

In[34]: a is b

Out[34]: False

 

배정구문 예2)
# 예제용 입력
In[36]: a = [9,9,9,9]
In[37]: b = a[:]             # 배정

# 서로 다른 객체임을 확인
In[38]: print('a id : ', id(a), '\nb id : ', id(b))
a id :  72336648 
b id :  72339208
In[39]: a is b
Out[39]: False

# 변수 변경시 다른 변수에서 값이 변경되지 않음
In[40]: a[3] = 101
In[41]: a
Out[41]: [9, 9, 9, 101]
In[42]: b
Out[42]: [9, 9, 9, 9]

In[43]: b.append(90)
In[44]: a
Out[44]: [9, 9, 9, 101]
In[45]: b
Out[45]: [9, 9, 9, 9, 90]


※ 다음 표는 각 자료형이 가변형(mutable)인지 불변형(immutable)인지 구분해놓은 표이다.

 자료형

 약어

 가변 불변 여부

 정수형

 int

 immutable

 실수형

 float

 immutable

 복소수형

 complex

 immutable

논리형 

 bool

 immutable

 문자열

 str

 immutable

 튜플

 tuple

 immutable

 집합형(불변형)

 flozenset

 immutable

 딕셔너리

 dict

 mutable

 리스트

 list

 mutable

 집합형(가변형)

 set

 mutable

 


반응형

댓글