[Python] 얕은복사 깊은복사 ([:], copy(),deepcopy)

Yewon Choi·2020년 6월 27일
3

Python

목록 보기
9/29

📌 자료형의 값 저장

📝 동일한 값인지 확인

>>> a = [1,2,3]
>>> b = a

>>> id(a)
4303029896
>>> id(b)
4303029896

👉 동일한 값

>>> a is b  # a와 b가 가리키는 객체는 동일한가?
True

📝 리스트를 복사 (다른 주소를 가리키도록)

1. [:] 이용

>>> a = [1, 2, 3]
>>> b = a[:]
>>> a[1] = 4
>>> a
[1, 4, 3]
>>> b
[1, 2, 3]

2. copy 모듈 이용

>>> from copy import copy
>>> b = copy(a)

>>> b is a
False

📝 얕은 복사(shallow copy)와 깊은 복사(deep copy)

🐥 1.mutable과 immutable 객체

객체에는 mutable과 immutable 객체가 있다.

list 는 mutable 이다.

>>> a = [1, 2, 3]
>>> id(a)
4393788808
>>> a[0] = 5
>>> a
[5, 2, 3]
>>> id(a)
4393788808

set도 mutable
|= set에서 or 연산으로 합집합이다
값은 변경되었으나 id는 변함없다.

>>> x = {1, 2, 3}
>>> x
{1, 2, 3}
>>> id(x)
4396095304
>>> x|={4,5,6}
>>> x
{1, 2, 3, 4, 5, 6}
>>> id(x)
4396095304

str은 immutable

s 변수에 첫번째 글자를 변경 시도하면 에러가 발생한다.
s에 다른 값을 할당하면, id가 변경된다.
재할당은 애초에 변수를 다시할당하는 것이므로 mutable과 immutable과는 다른 문제이다.
list또한 값을 재할당하면 id가 변경된다.

>>> s= "abc"
>>> s
'abc'
>>> id(s)
4387454680
>>> s[0]
'a'
>>> s[0] = 's'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> s = 'def'
>>> s
'def'
>>> id(s)
4388970768

🐥 2. 변수 간 대입

2-1 mutable한 객체의 변수 간 대입

list의 얕은 복사
b 에 a를 할당하면 값이 할당되는 것이 아니라 같은 메모리 주소를 바라본다.
b를 변경하면 같이 a도 바뀐다.
mutable한 다른 객체 또한 똑같은 현상이 나타난다.

>>> a = [1, 2, 3]
>>> b = a # shallow copy
>>> b[0]= 5
>>> a
[5, 2, 3]
>>> b
[5, 2, 3]
>>> id(a)
4396179528
>>> id(b)
4396179528

2-2 immutable한 객체의 변수간 대입

str 문자열의 얕은 복사
list와 똑같이 b를 a에 할당하면 같은 메모리 주소를 바라보게 된다.
하지만 b에 다른 값을 할당하면 재할당이 이루어지며 메모리 주소가 변경
고로 a와 b는 다른 값을 가진다.

>>> a = "abc"
>>> b = a
>>> a
'abc'
>>> b
'abc'
>>> id(a)
4387454680
>>> id(b)
4387454680
>>> b = "abcd"
>>> a
'abc'
>>> b
'abcd'
>>> id(a)
4387454680
>>> id(b)
4396456400

3. 얕은 복사(shallow copy)

list의 슬라이싱을 통한 새로운 값을 할당
아래의 결과와 같이 슬라이싱을 통해서 값을 할당하면 새로운 id가 부여되며, 서로 영향을 받지 않는다.

>>> a = [1,2,3]
>>> b = a[:]
>>> id(a)
4396179528
>>> id(b)
4393788808
>>> a == b
True
>>> a is b
False
>>> b[0] = 5
>>> a
[1, 2, 3]
>>> b
[5, 2, 3]

하지만, 이러한 슬라이싱 또한 얕은 복사에 해당
리스트안에 리스트 mutable객체 안에 mutable객체인 경우 문제가 된다.
id(a) 값과 id(b) 값은 다르게 되었지만, 그 내부의 객체 id(a[0])과 id(b[0])은 같은 주소를 바라보고 있다.

>>> a = [[1,2], [3,4]]
>>> b = a[:]
>>> id(a)
4395624328
>>> id(b)
4396179592
>>> id(a[0])
4396116040
>>> id(b[0])
4396116040

재할당하는 경우는 문제가 없다. 메모리 주소도 변경

>>> a[0] = [8,9]
>>> a
[[8, 9], [3, 4]]
>>> b
[[1, 2], [3, 4]]
>>> id(a[0])
4393788808
>>> id(b[0])
4396116040

하지만, a[1] 에 값을 변경하면 b[1]도 따라 변경

>>> a[1].append(5)
>>> a
[[8, 9], [3, 4, 5]]
>>> b
[[1, 2], [3, 4, 5]]
>>> id(a[1])
4396389896
>>> id(b[1])
4396389896

copy 모듈의 copy 메소드 또한 얕은 복사

>>> import copy
>>> a = [[1,2],[3,4]]
>>> b = copy.copy(a)
>>> a[1].append(5)
>>> a
[[1, 2], [3, 4, 5]]
>>> b
[[1, 2], [3, 4, 5]]

4. 깊은 복사(deep copy)

깊은 복사는 내부에 객체들까지 모두 새롭게 copy

copy.deepcopy메소드가 해결

>>> import copy
>>> a = [[1,2],[3,4]]
>>> b = copy.deepcopy(a)
>>> a[1].append(5)
>>> a
[[1, 2], [3, 4, 5]]
>>> b
[[1, 2], [3, 4]]

참고
https://wikidocs.net/16038

profile
https://github.com/devAon 찰나의 개발흔적을 남기는 개발블로그 입니다 🐥 https://aonee.tistory.com 에서 Velog로 블로그 이전 작업중입니다 ! 🎶

0개의 댓글