반응형
🧠 핵심 비유: 복사는 "노트 복사"다!
- 📄 얕은 복사: "노트의 표지와 차례를 복사하지만, 안에 낀 포스트잇은 원본과 공유"
- 📚 깊은 복사: "노트뿐 아니라 안의 포스트잇, 메모지, 첨부자료까지 전부 새로 복사"
📦 구조 예시로 보기
original = [1, 2, [3, 4]]
복사 종류 | 설명 |
copy.copy(original) | 리스트만 새로 만들고, 내부의 [3, 4]는 공유 |
copy.deepcopy(original) | 리스트도 새로, 내부의 [3, 4]도 새로 복사 |
🔍 차이 정리표
항목 | 얕은 복사 (copy.copy) | 깊은 복사 (copy.deepcopy) |
복사 대상 | 가장 바깥쪽 객체만 새로 만듦 | 모든 내부 객체까지 새로 만듦 |
내부 변경 영향 | 원본과 복사본에 모두 영향 | 복사본만 변경됨 |
속도 | 빠름 | 느림 |
메모리 사용 | 적음 | 많음 |
사용 시기 | 내부 객체가 안 바뀔 때 | 중첩된 객체도 바꾸고 싶을 때 |
✅ 코드 예제로 명확히 보기
import copy
original = [1, 2, [3, 4]]
# 얕은 복사
shallow = copy.copy(original)
# 깊은 복사
deep = copy.deepcopy(original)
# 내부 리스트 변경
original[2][0] = 999
print("원본:", original) # [1, 2, [999, 4]]
print("얕은 복사:", shallow) # [1, 2, [999, 4]] ← 내부 공유
print("깊은 복사:", deep) # [1, 2, [3, 4]] ← 독립 객체
🎯 언제 어떤 걸 써야 할까?
상황 | 권장 복사 방식 |
리스트 안에 숫자나 문자열만 있다 | 얕은 복사로 충분 |
딕셔너리 안에 리스트가 있고, 그걸 바꾸려 한다 | 깊은 복사 필요 |
복사 후 원본과 완전히 분리된 상태에서 작업하고 싶다 | 깊은 복사 필수 |
🧵 한 줄 요약
얕은 복사는 껍데기만 새로 만들고 안은 공유,
깊은 복사는 안까지 전부 새로 만든다.
✅ 정리: 얕은 복사 vs 깊은 복사 핵심 요약
개념 | 설명 |
얕은 복사 | 바깥 객체는 새로 만들지만, 내부 객체는 원본을 참조합니다. |
깊은 복사 | 바깥 객체뿐 아니라 내부 객체까지 전부 새로 복사합니다. |
불변 객체 (immutable) | int, float, str, tuple 등은 복사해도 참조나 다름없으며, 값을 절대 변경할 수 없음 |
🎯 개념별로 다시 정리해 드리면:
✅ 1. 얕은 복사 = 참조형 내부는 공유
import copy
a = [1, 2, [3, 4]]
b = copy.copy(a) # 얕은 복사
a[2][0] = 999
print(b) # [1, 2, [999, 4]] ← 내부 리스트는 a와 b가 **공유**
- a와 b는 바깥 리스트는 다르지만, 안의 [3, 4]는 같은 객체를 참조합니다.
✅ 2. 깊은 복사 = 내부까지 전부 새로 만들어서 독립적
c = copy.deepcopy(a)
a[2][0] = 777
print(c) # [1, 2, [999, 4]] ← 변경 안 됨, 완전히 분리됨
✅ 3. 불변 객체 (immutable) 는 복사든 참조든 차이 없음
x = "hello"
y = x
x = "world"
print(y) # hello ← 문자열은 값이 바뀌지 않음. 참조라도 상관 없음
- str, int, tuple 같은 불변 객체는 값을 바꿀 수 없기 때문에, 참조건 복사건 의미 차이가 없습니다.
- 따라서 얕은 복사와 깊은 복사의 차이는 '가변 객체(mutable)'가 내부에 있을 때만 중요합니다.
🧠 직관적 비유로 마무리
개념 | 비유 |
얕은 복사 | 책 표지를 복사하되, 안에 끼운 부록은 같이 공유 |
깊은 복사 | 책 표지와 부록까지 전부 새로 인쇄 |
불변 객체 | 돌덩이. 어디에 둬도 변하지 않고 공유해도 안전 |
✅ 핵심 정리 문장
"얕은 복사는 외형만 새로 만들고 내부는 여전히 원본을 참조한다.
깊은 복사는 내부까지 전부 복제한다.
불변 객체는 바뀌지 않으므로 복사나 참조나 결과가 같다."
📌 얕은 복사의 2가지 결과
내부 요소의 종류 | 복사 이후 변경 시 원본 영향 | 이유 |
불변 객체 (int, str, tuple) | ❌ 없음 | 값을 바꾸면 새 객체를 만든 것 |
가변 객체 (list, dict, set) | ✅ 있음 | 같은 객체를 참조하고 있기 때문 |
✅ 1. 불변 객체가 내부에 있을 때: 원본 영향 없음
import copy
a = [1, 2, 3]
b = copy.copy(a)
b[0] = 999 # 인덱스 0에 새 값 할당
print(a) # [1, 2, 3] → 원본 안 바뀜
- int는 불변 객체라 새 값을 할당하면 b[0]만 바뀜 (새 객체로 교체됨)
- 얕은 복사라 해도 불변 객체를 바꾸면 그냥 다른 값을 참조하게 되는 것
✅ 2. 가변 객체가 내부에 있을 때: 원본도 바뀜
a = [1, 2, [3, 4]]
b = copy.copy(a)
b[2][0] = 999
print(a) # [1, 2, [999, 4]] → 원본도 바뀜
- 내부의 [3, 4]는 리스트 → 가변 객체
- 얕은 복사에서는 내부 객체는 동일한 참조이므로, 내부 요소를 바꾸면 원본도 바뀜
📊 핵심 비교 표: 얕은 복사에서 값 변경 시 원본 영향
내부 요소 유형 | 예시 | 복사 후 요소 변경 | 원본 영향 여부 | 설명 |
불변 객체 | [1, 2, 3] | b[0] = 999 | ❌ 없음 | int는 값만 바뀌고 원본과 무관 |
가변 객체 | [1, 2, [3, 4]] | b[2][0] = 999 | ✅ 있음 | [3, 4]는 원본과 공유됨 |
🧠 추가 팁: 내부 객체가 몇 단계 더 중첩된 경우
a = [[1, 2], [3, 4]]
b = copy.copy(a)
b[0][0] = 100
print(a) # [[100, 2], [3, 4]] → 역시 변경됨
- 중첩되어 있어도, 내부 가변 객체는 모두 원본과 공유됨
- 중첩이 있는 경우에는 **깊은 복사 (copy.deepcopy)**를 써야 완전 분리 가능
✅ 한 줄 핵심
얕은 복사라도 내부에 있는 것이 불변 객체면 영향이 없고, 가변 객체면 원본이 바뀐다.
📌 사본 전달 vs 원본 전달 (참조 변수의 차이)
🎁 비유로 이해하기
개념 | 설명 | 비유 |
사본(copy) | 기존 리스트와 똑같지만 완전히 새로운 리스트를 만듦 | 프린터로 문서를 복사해서 새 종이로 만드는 것 |
참조(reference) | 기존 리스트를 가리키는 또 다른 변수 | 책상 위의 같은 책을 두 사람이 함께 보는 것 |
🧪 코드와 함께 보기
numbers = list(range(11)) # [0, 1, 2, ..., 10]
✅ 1. 슬라이싱을 통한 사본 생성
reversed_list = numbers[::-1] # ← 새 리스트가 만들어짐
reversed_list[0] = 99
- reversed_list는 numbers의 복사본
- reversed_list[0]만 바뀌고, numbers는 변하지 않음
📌 사본이므로 원본과는 완전히 별개
❌ 2. 단순 대입은 참조 공유
numbers2 = numbers
numbers2[0] = 11
- numbers2는 numbers와 같은 리스트를 함께 가리킴
- numbers2[0] = 11 하면 → numbers[0]도 바뀜
📌 같은 책을 두 개의 변수명이 함께 보고 있는 것
🔍 차이를 그림으로 이해하기
✅ 사본일 때
numbers → [ 0, 1, 2, 3, ..., 10 ]
reversed_list → [10, 9, 8, ..., 0 ] (별도의 리스트)
❌ 참조일 때
numbers ↘
→ [ 11, 1, 2, 3, ..., 10 ]
numbers2 ↗ (같은 리스트를 가리킴)
✅ 핵심 정리
비교 항목 | 사본(copy) | 참조(reference) |
생성 방식 | [:], [::-1], copy() | 단순 대입 a = b |
연결 관계 | 완전히 다른 리스트 | 같은 리스트 가리킴 |
원본 영향 | 없음 | 서로 영향 줌 |
예시 | reversed_list = numbers[::-1] | numbers2 = numbers |
🧠 Tip
- 사본을 만들고 싶으면 반드시 슬라이싱, .copy(), list() 등을 사용하세요.
- 참조가 필요할 땐 그냥 대입하면 됩니다.
반응형
'데이터 사이언스 > Python 프로그래밍' 카테고리의 다른 글
정규분포 통계 머신러닝 표준정규분포 확률밀도함수 평균 표준편차 시각화 데이터샘플링 히스토그램 (0) | 2025.07.09 |
---|---|
이터레이터(iterator) 메모리 효율성과 속도 스트리밍 처리 대규모 데이터 다루기 (0) | 2025.07.03 |
.format() 포멧 python 파이썬 print 프린트 (0) | 2025.06.19 |
python 파이썬 변수 데이터 타입 확장형for문 pop remove append insert (0) | 2025.06.18 |
python 파이썬 install .py .ipynb 비주얼 코드 visual studo code markdown (1) | 2025.06.18 |