파이썬의 객체를 다룰 때 무작정 복사를 하다 보면 원본 객체의 데이터가 변경되어 원치 않은 오류가 발생할 수 있다.
얕은복사(Shallow Copy)와 깊은복사(Deep Copy)는 객체를 복사하는 방법을 의미하고 이를 이해하기 위해선 mutable객체와 immutable객체에 대한 이해가 먼저 필요하다.
# c에서의 변수 저장
int a = 1; # a라는 저장공간에 1을 저장한다.
# python에서의 변수 저장
a = 1
# a와 1은 별개의 존재로, a는 1이라는 객체를 가리키고 있을 뿐
# a에 정수 1이 할당된 것이 아니다.
# ex) 리스트에 대한 변환
a = [1, 2, 3, 4]
id(a)
>>> 4393775432
a[0] = 6
a
>>> [6, 2, 3, 4]
id(a)
>>> 4393775432 #id값 그대로
# ex) 문자열에 대한 변환
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에 다른 값을 재할당하는 것으로 id가 변경된다. mutable과 immutable과는 다른 개념
s
>>> 'def'
id(s)
>>> 4388970768 # id값이 변한다.
**결론 : 파이썬의 변수는 값을 저장하는 것이 아닌 객체의 주소를 참조하는 c의 포인터와 같은 동작을 한다.
a = [1, 2, 3, [4, 5]]
b = a
print(id(a), id(b))
>>>
2265003288712 2265003288712
b[0] = 6
print(a, b)
print(id(a), id(b))
>>>
[6, 2, 3, [4, 5]], [6, 2, 3, [4, 5]]
2265003288712 2265003288712
a = [1,2,3,[4,5,6]]
b = a[:]
id(a)
>>> 4396179528
id(b)
>>> 4393788808
# immutable 자료의 변경
a[0] = 33
print(a, b)
>>> [33, 2, 3, [4, 5, 6]], [1, 2, 3, [4, 5, 6]]
'''
immutable 자료의 경우 변경하려는 값에서만 재할당이 일어나 id값이 달라지지만
나머지 값에서는 id값이 그대로이므로 얕은복사라고 본다.
'''
# mutable 자료의 변경
a[3].append(7)
print(a, b)
>>> [33, 2, 3, [4, 5, 6, 7]], [1, 2, 3, [4, 5, 6, 7]]
'''
mutable 자료의 경우에는 재할당이 일어나는 것이 아닌, a와 b에서 동시에 참조하고 있는
원본 값에서 추가가 일어난다. -> 동일하게 얕은 복사라 볼 수 있다.
'''
# mutable 자료 내의 immutable 자료 변경
a[3][1] = 150
print(a, b)
>>> [33, 2, 3, [150, 5, 6, 7]], [1, 2, 3, [150, 5, 6, 7]]
'''
이와 같이 mutable 자료형 안의 immutable 자료형을 변경할 때는 a만을 복사하는 것이고
각 요소에 대해서는 복사가 아닌 배정이 이뤄졌다고 추측한다.
'''
import copy
a = [1,2,3,[4,5,6]]
b = copy.copy(a)
id(a)
>>> 4396179528
id(b)
>>> 4393788808
# immutable 자료의 변경
a[0] = 33
print(a, b)
>>> [33, 2, 3, [4, 5, 6]], [1, 2, 3, [4, 5, 6]]
'''
immutable 자료의 경우 변경하려는 값에서만 재할당이 일어나 id값이 달라지지만
나머지 값에서는 id값이 그대로이므로 얕은복사라고 본다.
또한 재할당의 경우 원본에 영향을 주지 못한다.
'''
# mutable 자료의 변경
a[3].append(7)
print(a, b)
>>> [33, 2, 3, [4, 5, 6, 7]], [1, 2, 3, [4, 5, 6, 7]]
'''
mutable 자료의 경우에는 재할당이 일어나는 것이 아닌, a와 b에서 동시에 참조하고 있는
원본 값에서 추가가 일어난다. -> 동일하게 얕은 복사라 볼 수 있다.
'''
# mutable 자료 내의 immutable 자료 변경
a[3][1] = 150
print(a, b)
>>> [33, 2, 3, [150, 5, 6, 7]], [1, 2, 3, [150, 5, 6, 7]]
'''
이와 같이 mutable 자료형 안의 immutable 자료형을 변경할 때는 a만을 복사하는 것이고
각 요소에 대해서는 복사가 아닌 배정이 이뤄졌다고 추측한다.
'''
import copy
a = [1,2,3,[4,5,6]]
b = copy.copy(a)
id(a)
>>> 4396179528
id(b)
>>> 4393788878
# immutable 자료의 변경
a[0] = 33
print(a, b)
>>> [33, 2, 3, [4, 5, 6]], [1, 2, 3, [4, 5, 6]]
'''
본질적으로 다른 값을 참조하고 있으므로 한 값을 바꾼다 해서 다른 값에
영향을 미치지 않는다.
'''
# mutable 자료의 변경
a[3].append(7)
print(a, b)
>>> [33, 2, 3, [4, 5, 6, 7]], [1, 2, 3, [4, 5, 6]]
'''
mutable 자료 역시 본질적으로 다른 값이므로 영향을 받지 않는다.
'''
# mutable 자료 내의 immutable 자료 변경
a[3][1] = 150
print(a, b)
>>> [33, 2, 3, [150, 5, 6, 7]], [1, 2, 3, [4, 5, 6]]
'''
mutable 자료 내부의 immutable 자료의 변경 시에도 동일하게 영향을 받지 않는다.
'''