본문 바로가기

Programming/Python

[PYTHON] shallow copy와 deep copy를 알아보자 🌱

가변객체

파이썬의 객체는 가변객체(mutable)와 불변(immutable) 객체로 나뉜다. 가변객체에는 list, set, dict 등이 있으며, 불변객체와 달리 값을 수정하더라도 메모리주소가 바뀌지 않는다는 특징이 있다.
 
가변객체를 copy 할때의 주의사항과 shallow copy, deep copy에 대해 알아보자.
 

copy

a_list를 만든 후 b_list에 할당하고 메모리 주소값을 출력해 보았다.
 

a_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
b_list = a_list

print('Ex1 > ', id(a_list))
print('Ex1 > ', id(b_list))
# Ex1 >  2736207102336
# Ex1 >  2736207102336

b_list[2] = 100

print('Ex1 > ', a_list)
print('Ex1 > ', b_list)
# Ex1 >  [1, 2, 100, [4, 5, 6], [7, 8, 9]]
# Ex1 >  [1, 2, 100, [4, 5, 6], [7, 8, 9]]
# => call by refference, 둘 다 같은 요소를 참조

코드에서와 같이 두 리스트는 같은 메모리 주소를 공유하며 값을 수정했을 때 동시에 적용된다.
 
 

shallow copy

하지만 리스트의 복제가 필요한 경우 메모리 주소를 공유하면 원하는 결과를 얻을 수 없다. 이럴 때는 copy 함수를 사용할 수 있다.
 

import copy 

c_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
d_list = copy.copy(c_list)

print('Ex2 > ', id(c_list))
print('Ex2 > ', id(d_list))
# Ex2 >  2732678325632
# Ex2 >  2732678322048

d_list[1] = 100
print('Ex2 > ', c_list)
print('Ex2 > ', d_list)
# Ex2 >  [1, 2, 3, [4, 5, 6], [7, 8, 9]]
# Ex2 >  [1, 100, 3, [4, 5, 6], [7, 8, 9]]

 

두 객체는 주소를 공유하지 않고 한 리스트의 값을 변경하더라도 다른 리스트에 반영되지 않는 것을 확인할 수 있다.
 

 

d_list[3].append(1000)
d_list[4][1] = 10000
print('Ex2 > ', c_list)
print('Ex2 > ', d_list)
# Ex2 >  [1, 2, 3, [4, 5, 6, 1000], [7, 10000, 9]]
# Ex2 >  [1, 100, 3, [4, 5, 6, 1000], [7, 10000, 9]]

 

하지만 예제 코드와 같이 이중 리스트의 경우, 즉 객체 안의 객체의 경우 shallow copy는 이를 복사해주지 않는다.

 
 

geeksforgeeks

 

 

deep copy

객체를 그대로 복사해야 하는 경우 deep copy를 사용할 수 있다.

e_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
f_list = copy.deepcopy(e_list)

print('Ex3 > ', id(c_list))
print('Ex3 > ', id(d_list))
# Ex3 >  1752827766720
# Ex3 >  1752827763200

f_list[3].append(1000)
f_list[4][1] = 10000
print('Ex3 > ', e_list)
print('Ex3 > ', f_list)
# Ex3 >  [1, 2, 3, [4, 5, 6], [7, 8, 9]]
# Ex3 >  [1, 2, 3, [4, 5, 6, 1000], [7, 10000, 9]]

 

geeksforgeeks

 
 

📌주의사항
파이썬에서 copy 사용 시 무조건 deep copy를 사용하는 것에 앞서 객체의 자료형을 확인해야한다.