리스트와 참조값
파이썬에서 리스트 변수는 리스트 자체를 저장하고 있는 것이 아닌 참조값(reference)을 가지고 있다. 참조값은 메모리에서 리스트 객체의 위치이다. 쉽게 말해, 리스트 변수는 리스트 객체 자체가 아닌 그 주소를 가리키고 있다고 할 수 있다.
scores = [10, 20, 30, 40, 50]
values = scores
위 예제는 scores 리스트 객체를 values 변수에 복사하여 넣어둔 것처럼 보이지만 사실 scores와 values 변수는 모두 동일한 리스트 객체를 가리키고 있다.
그렇기 때문에 values를 통하여 리스트 요소의 값을 변경하면 scores 리스트도 변경이 된다.
scores = [10, 20, 30, 40, 50]
values = scores
values[3] = 60
print(scores) # [10, 20, 30, 60, 50]
![](https://t1.daumcdn.net/keditor/emoticon/friends2/large/060.png)
리스트를 복사해서 원본값의 변경 없이 복사본의 값만 변경하려 했다면 몹시 당황스럽다. 그렇다면 리스트를 올바르게 복사하려면 어떻게 해야 할까?
얕은 복사와 깊은 복사
list() 함수를 사용하면 리스트의 복사본을 생성할 수 있다.
scores = [10, 20, 30, 40, 50]
values = list(scores)
values[3] = 60
print(scores) # [10, 20, 30, 40, 50]
print(values) # [10, 20, 30, 60, 50
위 예제에서 알 수 있듯이, list() 함수를 사용하여 리스트의 복사본을 생성하면 원본 리스트는 그대로 있고, 복사본의 값만 변경되었다는 것을 볼 수 있다.
이런 방식으로 복사본을 만드는 것을 얕은 복사(shallow copy)라고 부른다. 얕은 복사라 불리는 이유는 이러한 복사가 한 단계 깊이(depth)까지만 적용이 되기 때문이다. 만약 원본의 리스트가 중첩된 리스트 같이 가변(mutable) 객체를 포함하고 있었다면 이 객체는 여전히 복사된 리스트와 원본 리스트 양쪽에서 공유가 되어 위에서 보았던 문제가 또 발생하게 되는 것이다.
![](https://t1.daumcdn.net/keditor/emoticon/friends2/large/083.png)
이렇게 말하면 이게 무슨 말인가 싶을 수 있으니 예제를 통해 살펴보자.
nested_scores = [[10, 20], [30, 40], [50, 60]]
shallow_copy = list(nested_scores)
shallow_copy[0][1] = 99
print(nested_scores) # [[10, 99], [30, 40], [50, 60]]
print(shallow_copy) # [[10, 99], [30, 40], [50, 60]]
위 예제에서 list() 함수를 사용했기 때문에 복사본이 잘 만들어졌을 것이라 생각했으나, 복사본의 중첩된 리스트 안의 요소를 1에서 99로 변경하니 원본 리스트에서도 변경이 이루어지고 있다. 이는 list() 함수가 리스트가 중첩된 경우 한 단계 깊이까지의 얕은 복사만 수행하기 때문이다.
만약 원본 리스트와 그 하위 객체들까지 독립된 복사본 리스트를 만들고 싶다면 깊은 복사(deep copy)를 수행해야 한다. 깊은 복사는 copy 모듈의 deepcopy()를 사용해 구현할 수 있다.
import copy
original_scores = [[10, 20], [30, 40], [50, 60]]
deep_copy = copy.deepcopy(original_scores)
deep_copy[0][1] = 99
print(original_scores) # [[10, 20], [30, 40], [50, 60]]
print(deep_copy) # [[10, 99], [30, 40], [50, 60]]
![](https://t1.daumcdn.net/keditor/emoticon/friends2/large/034.png)
야호! 이렇게 하위 객체의 변경이 서로에게 영향을 미치지 않는 완벽한 복사본을 만들어 냈다.
간단한 리스트의 경우에는 list()를 이용한 얕은 복사로도 충분할 수 있지만, 리스트가 중첩되어 있는 복잡한 경우에는 deepcopy()를 이용한 더 깊은 복사가 더 안전하다. 상황과 데이터 구조에 따라 적절한 방법을 선택하면 된다.
'Language > Python' 카테고리의 다른 글
[Python] 파이썬 리스트 컴프리헨션 (리스트 함축, List Comprehension) (0) | 2025.01.16 |
---|---|
[Python] 파이썬 리스트와 함수 (값으로 호출 vs 참조로 호출) (0) | 2025.01.16 |
[Python] 파이썬 리스트 비교, 정렬 (0) | 2025.01.15 |
[Python] 파이썬 리스트의 기초 연산들 (요소 추가, 삭제, 삽입 등) (0) | 2025.01.15 |
[Python] 파이썬 인덱싱과 슬라이싱 (0) | 2025.01.14 |