파이썬에는 깊은복사(deepcopy)와 얕은복사(shallowcopy)가 있습니다.
이 두 개념을 알기 전에 파이썬 객체들의 특성에 대해 파악해 보겠습니다.
1. mutable, immutable 객체
파이썬에서 변수는 자신에게 대입된 객체를 가리키는 일종의 포인터 같은 역할을 합니다. 변수는 저장공간을 가지지 않고 객체의 주소를 저장하고 있습니다.
a = 1
a는 1을 가지고 있는것이 아니라. 1이라는 integer객체의 주소를 가지고 있게 됩니다.
여기서 mutable의 개념이 나오게 됩니다. mutable속성의 객체는 다음과 같습니다.
class | 구분 |
list | mutable |
set | mutable |
dict | mutable |
bool | immutable |
int | immutable |
float | immutable |
tuple | immutable |
str | immutable |
frozenset | immutable |
예시1)
a = 1
b = a
print(a is b)
c = [1, 2, 3, 4]
d = c
print(c is d)
결과)
True
True
a와 b, c와 d는 같은 주소값을 참조(레퍼런스)하고 있습니다.
list는 mutable한 객체이기 때문에 다음과 같이 사용할 수 있습니다.
예시2)
a = 1
b = a
b = 0
print(a is b)
print(a)
print(b)
c = [1, 2, 3, 4]
d = c #shallow copy
d[1] = 0
print(c is d)
print(c)
print(d)
id() : 각 객체가 어떤 주소값(레퍼런스)를 참조하고 있는지 알 수 있게 해주는 함수입니다.
A is B : A와 B의 참조가 같은 경우 True를 반환합니다.(참조가 같다는것은 같은 객체를 가리킴을 의미)
A == B : A와 B의 값이 같은 경우 True를 반환합니다.
값과 참조 모두 같은지 알고 싶다면 is를 사용합니다.(같은 객체를 가리키면 값도 같을것)
값만 비교하고 싶을때는 == 또는 !=를 사용
결과)
False
1
0
True
[1, 0, 3, 4]
[1, 0, 3, 4]
interger는 immutable객체이고 list는 mutable객체이기 때문에 다음과 같은 결과가 나왔습니다.
interger는 immutable하기 때문에 False가 나오고 b의 값만 바뀌었습니다.
list안의 요소가 바뀌었는데 mutable하기 때문에 d를 수정하면 c까지 바뀌게 됩니다.
예시3)
a = 1
b = a
print(id(a), id(b)) #1
print(a is b)
c = [1, 2, 3, 4]
d = c
print(id(c), id(d)) #2
print(c is d)
b = 0
d[1] = 0
print(id(a), id(b)) #3
print(a is b)
print(id(c), id(d)) #4
print(c is d)
결과)
2204791341296 2204791341296
True
2204796332224 2204796332224
True
2204791341296 2204791341264
False
2204796332224 2204796332224
True
#1 : immutable한 객체인 integer를 복사했기 때문에 참조하는 주소값도 같고 값도 같습니다.
#2 : mutable한 객체 list를 복사했기 때문에 참조하는 주소값도 같고 값도 같습니다.
#3 : immutable한 객체인 interger를 변경했기 때문에 참조하는 주소값도 다르고 값도 다르게 됩니다.
#4 : mutable한 객체인 list를 변경했기 떄문에 얕은복사에 의해 주소도 같고 값도 같다고 출력됩니다.
여기서 #4의 값을 출력해보면
print(c)
print(d)
#[1, 0, 3, 4]
#[1, 0, 3, 4]
다음과 같이 얕은복사(주소값 복사)에 의해 d만 바꿨는데 c도 같이 바뀌게 된것을 알 수 있습니다.
2. 깊은 복사(deep copy)
깊은 복사는 전체 복사로 참조값의 복사가 아니라 참조된 객체 자체를 복사하는 것을 의미합니다.
그래서 깊은 복사는 내부의 객체들까지 모두 새롭게 copy가 됩니다.
import copy의 copy.deepcopy메소드를 이용하여 사용합니다.
원본 배열을 유지하기 위해 '깊은 복사'를 사용합니다.
예시)
import copy
a = [1, 2, 3, 4]
b = copy.deepcopy(a)
b[1] = 0
print(id(a), id(b))
print(a == b)
print(a is b)
print(a, b)
결과)
1266851993280 1266851544448
False
False
[1, 2, 3, 4] [1, 0, 3, 4]
깊은 복사를 하였기에 출력되는 주소도 다르고 값을 변경해주었기 때문에 값도 다르다 그래서 is 연산자에서도 False가 나오게 됩니다.
예시2)
import copy
a = [[1, 2], [1, 2, 3, 4]]
b = copy.deepcopy(a)
a[0].append(3)
print(a)
print(b)
결과)
[[1, 2, 3], [1, 2, 3, 4]]
[[1, 2], [1, 2, 3, 4]]
원본인 a에는 3을 추가했기 때문에 a[1]이 [1, 2, 3]이 되었고, b는 원본을 유지한 채로 출력이 되었습니다.
'[Python]' 카테고리의 다른 글
[Python] 파이썬 정규표현식(regular expression) (0) | 2023.07.04 |
---|---|
[Python] 파이썬 예외처리(try~except) (0) | 2022.09.17 |
[Python] 파이썬 : 람다(lambda) 함수 (0) | 2022.08.19 |
[Python] 파이썬 진수 변환 hex(), oct(), bin(), int() (0) | 2022.08.07 |
[Python] 파이썬 remove(), pop(), del 차이점 (0) | 2022.07.27 |