리스트와 참조값
파이썬에서 리스트 변수는 리스트 자체를 저장하고 있는 것이 아닌 참조값(reference)을 가지고 있다. 참조값은 메모리에서 리스트 객체의 위치이다. 쉽게 말해, 리스트 변수는 리스트 객체 자체가 아닌 그 주소를 가리키고 있다고 할 수 있다.
scores = [10, 20, 30, 40, 50]
values = scores
위 예제는 scores 리스트 객체를 values 변수에 복사하여 넣어둔 것처럼 보이지만 사실 scores와 values 변수는 모두 동일한 리스트 객체를 가리키고 있다.
![](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
그렇기 때문에 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 |