얕은 복사(shallow copy)는 바깥 컨테이너만 새로 만들고 안에 든 객체는 원본과 같은 객체를 가리킨다. 깊은 복사(deep copy)는 안쪽 객체까지 재귀적으로 새로 만든다. 중첩된 리스트·딕셔너리를 복사한 뒤 원본이 같이 바뀌는 버그의 원인이 대부분 이 차이다.
import copy
orig = [ [1, 2], [3, 4] ]
shallow = orig.copy() # list(orig), orig[:] 도 얕은 복사
deep = copy.deepcopy(orig)
shallow[0].append(99)
orig # [ [1, 2, 99], [3, 4] ] ← 안쪽 리스트를 공유
deep # [ [1, 2], [3, 4] ]==와 is
==는 값이 같은지 비교한다(__eq__)is는 같은 객체인지 비교한다.id(a) == id(b)와 같다None비교는is None으로 한다. 작은 정수·짧은 문자열은 인터프리터가 객체를 재사용해is가 우연히 참일 수 있으니, 값 비교에is를 쓰지 않는다
a = [1, 2]; b = [1, 2]; c = a
a == b # True (값이 같다)
a is b # False (다른 객체)
a is c # True (같은 객체를 가리키는 다른 이름)언제 무엇을
- 변수에 대입하는 것(
c = a)은 복사가 아니라 이름을 하나 더 붙이는 것이다 - 안쪽이 모두 불변(숫자·문자열·튜플)이면 얕은 복사로 충분하다
- 중첩된 가변 객체를 독립적으로 고쳐야 하면 깊은 복사. 대신 느리고, 파일 핸들처럼 복사할 수 없는 객체가 섞이면 실패한다
- 애초에 고치지 않고 새 값을 만드는 방식으로 쓰면 복사 고민이 줄어든다. 튜플·
frozenset·불변 데이터클래스(frozen=True)를 쓴다
자바스크립트의 전개 문법(spread syntax, {...obj})과 structuredClone도 같은 구분을 가진다. 얕은 병합이 보안 문제로 이어지는 예는 프로토타입 오염, 함수 기본값이 공유되는 문제는 가변 기본 인자 함정, 불변 값의 장점은 값 객체와 React 상태 갱신의 불변 업데이트를 본다.