일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- gradle
- Java
- OOM
- go
- 주키퍼
- 알고리즘
- 동적프로그래밍
- boj
- leetcode
- programmers
- Python
- HBase
- scala
- redis
- 자바
- zookeeper
- dynamic programming
- docker
- Go언어
- 파이썬
- 코드워
- 스칼라
- Linux
- 문제풀이
- 튜토리얼
- golang
- DP
- 프로그래머스
- codewars
- 리눅스
- Today
- Total
파이문
파이썬 얕은 복사와 깊은 복사 본문
파이썬 얕은 복사와 깊은 복사
(Python shallow copy, deep copy)
파이썬에서 리스트나 대부분의 컬렉션을 복사하는 가장 손 쉬운 방법은 그 자료형 자체의 내장 생성자를 사용하는 것이다.
>>> l1 = [3, [55, 44]]
>>> l2 = list(l1) # l2 = l1[:]
>>> l2
[3, [55, 44]]
>>> l1 == l2
True
>>> l1 is l2
False
그러나 생성자나 [:] 키워드를 사용하면 얕은 복사(Shallow Copy)를 사용하게 된다. 사본은 원래 컨테이너에 들어 있던 동일 객체에 대한 참조로 채워지게 된다. 이 방식은 모든 항목이 불변형이면 메모리를 절약할 수 있지만 가변 항목이 들어있을 경우 예상치 못한 결과를 받게 될 수도 있다.
>>> l1 = [3, [66, 55, 44], (7, 8, 9)]
>>> l2 = list(l1)
>>> l1.append(100)
>>> l1[1].remove(55)
>>> l2[1] += [33, 22]
>>> l2[2] += (10, 11)
위와 같은 예제에서 과정은 다음처럼 진행된다.
우선 l1의 사본인 l2가 생성된다.
이 때 l1의 리스트 값은 얕은 복사로 생성되었지만 내부의 [66, 55, 44]와 (7, 8, 9)는 동일한 객체를 가르키게 된다.
l1에 100을 append하면 l1의 리스트 객체에만 100이 추가되지만 l1[1]에 remove를 하면 l2도 가르키는 l2의 첫번째 값, 리스트에 55가 제거된다.
이후 l2의 두번째 값인 튜플에 값을 추가하면 다음과 같이 변한다.
리스트와 다르게 튜플에 값을 추가하자 새로운 튜플 객체가 생성되었다. 그 이유는 튜플에 값을 추가하게 되면 새로운 튜플이 생성되기 때문이다(튜플은 불변형이다). id 함수를 통해 각각의 고유 주소 값을 확인해보자. l1[0], l2[0]이 동일하고 l1[1], l2[1]이 동일했다가, 튜플에 새로운 값을 추가하고 난 이후에 l1[1]과 l2[1]의 값이 달라지는 것을 확인할 수 있다.
자료형이 불변형인지 가변형인지에 따라서 전혀 예상하지 못한 값을 받게 될 수 있다. 그렇기에 조심해야 하는 부분이기도 하다.
객체의 깊은 복사와 얕은 복사
얕게 복사한다고 해서 늘 문제가 생기는 것은 아니지만, 내포된 객체의 참조를 공유하지 않도록 깊게 복사할 필요가 있는 경우가 있다. 이 때는 내장 모듈인 copy 모듈을 사용하면 된다.
깊은 복사의 경우는 deepcopy를, 얕은 복사인 경우는 copy 함수가 이를 지원한다.
아래는 deepcopy의 예제이다.
>>> from copy import deepcopy
>>> lst1 = ['a','b',['ab','ba']]
>>> lst2 = deepcopy(lst1)
>>> lst2[2][1] = "d"
>>> lst2[0] = "c";
>>> print(lst2)
['c', 'b', ['ab', 'd']]
>>> print(lst1)
['a', 'b', ['ab', 'ba']]
lst2의 2번째 인덱스인 리스트 값을 변경하였지만 lst1의 값은 변경되지 않는 것을 확인할 수 있다.
반대로 deepcopy를 copy로만 바꾸어서 실행해보자. lst2의 리스트 값은 변경되지 않고 0번째 인덱스만 바뀐것을 확인할 수 있을 것이다.
deepcopy의 실행 결과
copy의 실행 결과
마지막으로 깊은 복사가 너무 깊이 복사하지 않도록, 복사하면 안 되는 리소스를 참조하지 않도록 조심해야 한다.
참고
http://www.python-course.eu/deep_copy.php
같이 보면 좋을 게시글
'Python > Python' 카테고리의 다른 글
파이썬에서 언더바의 의미 (0) | 2017.01.17 |
---|---|
파이썬 클래스 상속 (0) | 2017.01.16 |
파이썬에서 switch-case문 사용하기 (0) | 2016.05.25 |
파이썬에서 딕셔너리 키 값 체크하기 (1) | 2016.04.22 |
파이썬에서의 getter와 setter (0) | 2016.04.22 |