[Python TIL] 얕은 복사(Shallow copy)와 깊은 복사(Deep copy)
리스트 복사와 reverse() 메서드의 함정
오늘은 Python에서 리스트를 복사할 때 흔히 발생하는 실수를 다뤄보겠습니다.
리스트를 복사한 후 reverse()를 사용했는데, 원본 리스트까지 바뀌는 현상을 본 적이 있나요?
❌ 문제 코드
아래 코드를 실행하면 원본 리스트까지 뒤집혀버리는 문제가 발생해요.
string = list(input())
string_copy = string # 얕은 복사 (shallow copy)
string_copy.reverse()
print(string, string_copy)
예를 들어, "hello"를 입력하면 기대한 출력은:
['h', 'e', 'l', 'l', 'o'] ['o', 'l', 'l', 'e', 'h']
인데, 실제로는:
['o', 'l', 'l', 'e', 'h'] ['o', 'l', 'l', 'e', 'h']
처럼 원본 리스트(string)까지 바뀌어버려요.
왜 이런 일이 발생할까? 🤔
string_copy = string은 얕은 복사(shallow copy) 로,string_copy와 string이 동일한 리스트 객체를 가리키게 돼요.
즉, string_copy.reverse()를 호출하면 원본 리스트도 같이 뒤집히게 됩니다!
✅ 원본을 유지하는 해결 방법
원본 리스트를 유지하면서 새로운 리스트를 뒤집고 싶다면 깊은 복사(deep copy) 가 필요합니다.
🔹 방법 1: 슬라이싱 활용
string = list(input())
string_copy = string[:] # 원본을 새로운 리스트로 복사
string_copy.reverse()
print(string, string_copy)
💡 [:] 슬라이싱을 사용하면 원본과 같은 요소를 가진 새로운 리스트가 생성됩니다.
🔹 방법 2: copy() 메서드 활용
string = list(input())
string_copy = string.copy() # 새로운 리스트로 복사
string_copy.reverse()
print(string, string_copy)
💡 copy() 메서드도 리스트의 복사본을 생성해줍니다.
🔹 방법 3: reversed() 사용
string = list(input())
string_copy = list(reversed(string)) # 새로운 리스트로 변환
print(string, string_copy)
💡 reversed()는 원본을 수정하지 않고, 뒤집힌 새로운 iterator를 반환합니다.
이를 list()로 변환하면 원본이 유지된 채로 새로운 리스트를 만들 수 있습니다.
📝 정리
| 방법 | 원본 유지 | 속도 | 가독성 |
[:] | ✅ | 빠름 | 직관적 |
.copy() | ✅ | 빠름 | 명확함 |
reversed() | ✅ | 느림 (iterator 변환 필요) | 가장 깔끔 |