개요
2023.12.14 - [Python] 불변 객체 (Immutable)
2023.12.15 - [Python] 가변 객체 (Mutable)
위 두 개 글에서 불변 객체와 가변 객체에 대해 정리했는데, 이 글에서는 얕은 복사에 대해 정리해보려고 한다.
얕은 복사
얕은 복사(Shallow copy)란 객체의 참조값, 주소값만 복사하는 것을 의미한다. 객체의 주소값을 복사하기 때문에 복사된 값에 변경이 발생하면 복사한 값도 영향을 받아 두 변수 간에 독립성이 성립하지 않게 되는 특징이 있다.
다만, 변수의 독립성과 관련해서는 참조한 객체가 가변 객체인 경우에만 문제가 되며, 관련해서는 사실 2023.12.15 - [Python] 가변 객체 (Mutable)에서 살펴보았다.
따라서 이 글에서는 얕은 복사를 수행하는 방법을 위주로 정리한다.
1. 할당(=) 연산자 사용
a = "python2"
b = a
print(f'a={a}, id(a)={id(a)}')
print(f'b={b}, id(b)={id(b)}')
print('\n--값 갱신--')
a = "python3"
print(f'a={a}, id(a)={id(a)}')
print(f'b={b}, id(b)={id(b)}')
2. 슬라이싱
슬라이싱을 이용하여 가변 객체를 복사하면 복사한 변수가 참조하는 주소값이 달라져 얕은 복사가 아닌 것처럼 보인다.
a = ["python2", ["python3"]]
b = a[:]
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
하지만 각 원소의 주소값까지 확인해보면 가변 객체를 참조하는 원소는 같은 주소값을 참조하고 있는 것을 확인할 수 있다.
따라서 가변 객체인 원소의 상태를 변경하면, 복사한 변수에도 영향을 미치는 것을 알 수 있다.
a = ["python2", ["python3"]]
b = a[:]
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
print('\n--값 갱신--')
a.append(22)
a[1].append('python4')
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
이런 경우에도 얕은 복사로 취급하는데, 그림으로 표현하면 아래와 같다.
3. copy 함수 사용
객체 클래스가 제공하는 copy 함수는 슬라이싱을 하는 것과 동일하게 동작한다.
a = ["python2", ["python3"]]
b = a.copy()
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
print('\n--값 갱신--')
a.append(22)
a[1].append('python4')
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
4. copy 모듈의 copy 함수 사용
copy 모듈의 copy 함수 또한 슬라이싱할 때와 동일하게 동작한다.
from copy import copy
a = ["python2", ["python3"]]
b = copy(a)
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
print('\n--값 갱신--')
a.append(22)
a[1].append('python4')
print(f"""a={a}, id(a)={id(a)}""")
print(f"""b={b}, id(b)={id(b)}""")
불변 객체의 경우
불변 객체인 경우, 객체의 상태를 변경하면 항상 참조하는 메모리의 주소가 달라진다.
참고 문서
[파이썬/Python] 얕은 복사(Shallow copy)와 깊은 복사(deep copy)에 대한 완벽 정리
[python] 파이썬 얕은복사, 깊은복사 (copy, deepcopy, [:], =) 총 정리