본문 바로가기
컴퓨터 언어/Python

[ Python 3 ] 딕셔너리(dictionary) 복사시 주의!! ( copy, deepcopy )

by SuperMemi 2022. 8. 13.
반응형

[ Python 3 ] 딕셔너리 복사시 주의!! ( copy, deepcopy )


이전글 

딕셔너리 ( {}, dict ()) 생성

 

[ Python 3 ] 딕셔너리 타입 ( {}, dict ()) 생성

[ Python 3 ] 딕셔너리 타입 ( dict (), key, value ) 1. 딕셔너리 (dictionary) 타입이란? 딕셔너리 타입은 키(Key; immutable)와 값(value; mutable)으로 매핑되어 있는 순서가 없는 집합입니다. 다..

supermemi.tistory.com

딕셔너리 주의할 점(key type, 인덱싱 가능?, 중복될 경우엔?)

 

[ Python 3 ] 딕셔너리 타입 주의할 점(key type, 인덱싱 가능?, 중복될 경우엔?)

[ Python 3 ] 딕셔너리 타입 주의할 점(key type, 인덱싱 가능?, 중복될 경우엔?) 이전글 : 2022.08.13 - [분류 전체보기] - [ Python 3 ] 딕셔너리 타입 ( dict (), key, value ) ## 주의 1 : Key..

supermemi.tistory.com

 


딕셔너리 복사하기

 

복사라는 말이 내포하고 있는 뜻은 조금 심오합니다.

프로그래밍 언어마다 차이가 있지요.

 

값자체를 새로운 메모리에 담아서 복사할 것인가?

아니면 값을 담고 있는 메모리 주소를 복사할 것인가?

 

딕셔너리는 key와 value로 되어 있는데 이 경우에는 어떻게 될까요?

 

파이썬에서는 복사를 하는 방식에 따라 값이 바뀌기도 합니다.

모르고 사용하면 언젠가 큰일이 날 수 있으니 잘 알아 두어야 합니다!!

 


1. 할당하기

 

가장 기본적으로 생각할 수 있는 방법이죠.

 

dict_a = dict([['class','dog']])
dict_b = dict_a

print(dict_a, dict_b)

 

a의 내용이 b에도 담기게 됩니다.

별 문제가 없어 보입니다.

 

하지만 자세히보면 문제가 생길 수도 있습니다.

 

dict_a = dict([['class','dog']])
dict_b = dict_a

print(dict_a, dict_b)

dict_a['class'] = 'cat'

print(dict_a, dict_b)

 

분명히 복사를 하고 나서, dict_a의 값을 바꾸었는데!!!!!!!!!

왜 dict_b도 값이 바뀌어버린 것인가.....?!!!!!

 

이것은 사실 파이썬이 할당을 하면 메모리 주소를 복사해서 주기 때문입니다.

 

id() 를 사용하여 저장된 위치를 보면 간단합니다.

 

print(id(dict_a),id(dict_b))
print(id(dict_a['class']),id(dict_b['class']))

 

dict_a, dict_b 의 주소값이 같음을 볼 수 있습니다.

또한 구체적인 key의 value가 저장된 위치가 같음을 볼 수 있습니다.

 

이러니 구체적인 값을 바꾸면 따라서 바뀌게 되지요..

모르고 쓰면 눈뜨고 코가 잘려나가는...

 


2. copy() 이용하기

 

dict.copy( ) 라는 메소드를 사용할 수도 있습니다.

 

dict_a = dict([['class','dog']])
dict_b = dict_a.copy()

print(dict_a, dict_b)

dict_a['class'] = 'cat'

print(dict_a, dict_b)

 

print(id(dict_a),id(dict_b))
print(id(dict_a['class']),id(dict_b['class']))

 

copy()라는 메소드를 사용하여 딕셔너리 자체의 주소값은 동일하지만,

key의 value는 이와 달리 새로운 메모리에 값을 저장하여 독립되었다고 볼 수 있습니다.

 

그렇다면 여기서 끝일까요??

 

당연히 아닙니다.

 

copy()를 사용하더라도 여전히 값이 변할 수 있습니다.

 

중첩된 딕셔너리의 예시입니다.

 

dict_a = dict([['class',{'dog':[0,0,1]}]])
dict_b = dict_a.copy()

print(dict_a, dict_b)

dict_a['class']['dog'] = [0,1,0]

print(dict_a, dict_b)

 

중첩된 딕셔너리의 메모리 주소를 그냥 복사한다는 것을 볼 수 있습니다.

 

print(id(dict_a),id(dict_b))
print(id(dict_a['class']),id(dict_b['class']))
print(id(dict_a['class']['dog']),id(dict_b['class']['dog']))

 

따라서 copy() 또한 얕은 복사라고 할 수 있습니다.

 


3. deepcopy() 이용하기

 

중첩된 데이터까지 완전하게 독립된 복사를 원한다면 copy 모듈의 deepcopy() 함수를 사용해야 합니다.

 

import copy

dict_a = dict([['class',{'dog':[0,0,1]}]])
dict_b = copy.deepcopy(dict_a)

print(dict_a, dict_b)

dict_a['class']['dog'] = [0,1,0]

print(dict_a, dict_b)

print(id(dict_a),id(dict_b))
print(id(dict_a['class']),id(dict_b['class']))
print(id(dict_a['class']['dog']),id(dict_b['class']['dog']))


[ 다음 글 ] 

딕셔너리 메소드 함수들 ( update, items, keys, values, fromkeys, clear, pop, popitem, setdefault, get, copy)

 

[ Python 3 ] 딕셔너리 메소드 함수들 ( update, items, keys, values, fromkeys, clear, pop, popitem, setdefault, get, cop

[ Python 3 ] 딕셔너리 메소드 함수들 [ 이전 글 ] 딕셔너리 타입 ( {}, dict ()) 생성 [ Python 3 ] 딕셔너리 타입 ( {}, dict ()) 생성 [ Python 3 ] 딕셔너리 타입 ( dict (), key, value ) 1..

supermemi.tistory.com


 

반응형