일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 프로그래머스 # sql #mysql # 코딩테스트 # recursive cte
- 딥러닝 # GPU # 프레임워크 # 엣지 AI # GTC 2020 Online
- 프로그래머스 # 코딩테스트 # SQL # mysql # 차집합
- 프로그래머스 # sql # mysql # 코딩테스트 # 연습
- spark#apache spark#입문#스파크#빅데이터
- udacity#유다시티#자료구조#알고리즘#기초
- 파이썬 # python # copy
- mysql # SQL # 프로그래머스 # 코딩테스트
- NVIDIA # GTC 2020 # Webinar # GTC 행사
- github
- 딥러닝#초보#MLE#Cross-entropy#메모
- inflearn
- Git
- Today
- Total
from Karte,
파이썬에서의 deepcopy 와 shallow copy feat. copy module 본문
* 파이썬 전문가가 작성한 글이 아니라 내용 오류가 있을 수도 있는 점 유의 바랍니다. 혹시 오류 발견 시 댓글로 알려주시길 부탁드립니다.
* 포스팅 작성 시 참고한 소스들은 아래 References 에 기재하였으니 원문 확인이 필요하신 분들은 참고해 주시면 됩니다.
누군가에겐 너무나도 기본적인 내용일 수도 있지만, 나는 파이썬을 프로그래밍 언어로서 접하지 않고 데이터 분석 언어로서 처음 접했다. 그러다 보니 이제까지는 CS ( Computer Science ) 적인 이야기가 나오면 주춤하곤 했는데, 이제는 그러기 싫어서 파이썬 카테고리를 새로 생성했다. 앞으로 프로그래밍 관점에서의 파이썬 토박 상식을 주로 포스팅 할 예정이다.
파이썬 카테고리의 올라갈 첫 번째 글은 바로 파이썬에서의 객체 복사 ( copy ) 와 관련된 글이다. 연습 목적이든 대회 출전의 목적이든 보통 데이터 분석을 하면 원본 데이터는 적재한 상태 그대로 두고, 원본 데이터의 복사본을 만들어 여러 가지 피처들을 테스트 해보려고 하게 되는데, 그럴 때 필요한 copy 모듈과 파이썬에서의 copy 관련 개념을 정리해 보려 한다.
Assignment Operator ( = , 할당 연산자) vs Shallow Copy (얕은 복사) vs Deep Copy ( 깊은 복사 ) ?
파이썬에서 이미 정의된 객체를 복사할 수 있는 - 혹은 표면적으로는 복사를 한 것처럼 보이는, 그러나 실제로는 절대 아닌 - 방법에는 3가지가 있다. 할당 연산자 = 을 쓰거나, shallow copy 를 하거나 아니면 deepcopy 를 하거나! 하나씩 알아보자.
1. 할당 연산자 ( = )
아래 코드 블럭에서 보이는 것처럼 이미 정의된 변수를 새로운 변수에 할당하는 것이다.
a = ['orange', 500, 'kiwi', 450, ['pitaya', 'dragon fruit'], 1000] # 과일 이름과 가격이 저장된 리스트
b = a # 할당 연산자로 새로운 변수 b 에 a 를 저장
그런데 중간에 오렌지 가격이 600 으로 올라서 변수에 반영을 하되, 이전 가격은 a 에 그대로 저장을 하고 b 의 오렌지 가격만 변경을 해주어야 하는 상황이 있다고 억지스럽지만 가정하면,
b[1] = 600 # b에서만 오렌지 가격 변경
위와 같이 코드를 입력하면 되는 게 아닌가? 라고 생각을 할 수도 있다. ( 나도 처음에는 그랬다 ) 그렇지만 아니다!
할당 연산자를 저렇게 쓰면 a 객체를 복사하고, 그 값을 다시 b 에 저장하는 방식으로 동작할 것 같지만 그냥 그렇게 보일 뿐이고, 실제로는 전혀 아니다. 결과를 보면 a 변수의 값 또한 같이 변해있을 것이다.
할당 연산자의 역할은 변수와 값을 묶어주는 ( binding ) 일을 한다. 조금 더 자세히 말하면, 원래 a 변수가 가리키고 있던 위의 과일 이름과 가격이 저장된 리스트의 메모리 주소를 b 변수도 가리킬 수 있게 해주는 것이다. ( '가리키다' 라는 단어가 C 언어의 포인터를 연상되게 해서 되도록 쓰고 싶지 않았으나 달리 더 좋은 표현이 떠오르지 않았다...파이썬에는 포인터 개념이 없음에 주의! ) 따라서 b = a 를 실행 후 b 변수에서 인덱싱을 통해 다른 값을 입력하려고 한다면 a 변수의 값도 같이 변하게 되는 것이다. 그림으로 표현하면 아래와 같다.
2. Shallow copy & Deep copy ( copy 모듈 임포트해야 사용 가능한 복사 방식 )
shallow copy 와 deep copy 를 구분하는 기준은 '복합객체를 복사할 때의 과정이 재귀적인가?' 이다. shallow copy 는 복사 과정이 재귀적이지 않은 반면, deep copy 는 재귀적이다.
참고: 구글링을 해보니 list, dict, set 과 같이 객체 내부에 또 다른 객체를 담을 수 있는 자료형을 복합객체 ( compound object ) 라고 부른다고 한다.
shallow copy 는 할당 연산자와 달리 새로운 객체를 생성은 하되, 내부의 요소들은 기존의 객체의 원소들을 참조한다. 한 마디로 말하자만 껍데기는 새로 생성하되 알맹이들은 새로 생성하지 않고 기존에 선언되어 저장된 메모리 상의 위치를 참조하는 것이다.아래 References 의 4번 문서에서는 이 같은 성질을 'one level deep' 이라고 표현했다. 즉, list of lists 와 같은 구조일 경우 가장 바깥의 list 껍데기 ( one level deep )는 새로 생성이 되지만, list 내의 list 는 그렇지 않으므로 변수 b 에서 ['pitaya', 'dragon fruit'] 의 값을 바꾸면 a 에서도 값이 변한다. shallow copy 동작을 그림으로 표현하면 다음과 같다.
이제 shallow copy 를 구현하는 코드를 보자!
import copy # shallow copy / deep copy 구현을 위해 필요한 모듈
a = ['orange', 500, 'kiwi', 450, ['pitaya', 'dragon fruit'], 1000] # 과일 이름과 가격이 저장된 리스트
b = copy.copy(a) # copy 모듈의 copy 함수로 기존의 a 변수를 shallow copy 가능
shallow copy 를 한 상태에서 b 변수의 값을 일부만 변경시킨 후 a 변수를 확인하면 아래 캡처와 같다.
b 변수를 shallow copy 하면서 one level deep 했던 가장 바깥의 [] 와 원소들은 다른 객체로서 생성이 되어 b[0] = 'berries' 를 실행해도 a 변수에는 변함이 없으나, 내부의 [ 'pitaya', 'dragon fruit'] 까지는 새로 생성이 되지 않아 b[4][1] = '용과' 라고 값 변경을 하니 a 변수에도 변경사항이 반영이 된 것을 알 수 있다.
반면 deep copy 는 복사 과정이 재귀적이다. 기존의 복합 객체를 복사하여 완전히 다른 객체를 생성한다. 아래 그림에서 보는 것처럼 기존의 변수와 값은 같으나 완전히 다른 객체를 생성해 준다. 흔히 상상하는 copy 의 이미지와 동일한 동작을 수행하는 것이라는 생각이 든다.
구현은 아래와 같이 copy 모듈의 deepcopy 함수를 쓰면 된다.
import copy # shallow copy / deep copy 구현을 위해 필요한 모듈
a = ['orange', 500, 'kiwi', 450, ['pitaya', 'dragon fruit'], 1000] # 과일 이름과 가격이 저장된 리스트
b = copy.deepcopy(a) # copy 모듈의 deepcopy 함수로 기존의 a 변수를 deep copy 가능
다음과 같이 b 변수의 값의 일부를 변경시켜도 a 변수에는 반영이 안되는 것을 확인할 수 있다.
이 때문에 개인적으로 데이터 분석을 할 때는 deepcopy 를 많이 쓸 것 같다.
이걸로 첫 파이썬 관련 개념 정리 포스팅을 마치려고 한다. 내용적인 면이나 형식 면에서 아쉬움이 없지는 않으나 이제 겨우 첫 술을 들이킨 셈 치고...아직 마실 술이 많기에 벌써 배부르면 안된다는 생각으로 포스팅을 마친다.
References
1. GeeksforGeeks : Copy in Pyhton ( Deep Copy and Shallow Copy )
2. Python 3 Documentation : copy module
'study log > Python' 카테고리의 다른 글
[Udacity] Intro to Data Structures and Algorithms : Lesson #1. Introduction and Efficiency (0) | 2020.11.17 |
---|