List 생성, 복사, 수정을 할 때, Deep Copy와 Shallow Copy가 일어나는 문법들을 구분하여 사용하지 않는다면, 내가 다루는 자료의 내용이 원치 않는 결과로 이어질 수 있다. Mutable한 List 생성, 복사, 수정을 할 수 있는 문법들과, 이들이 return하는 결과값을 정확히 알고 정리하는 것이 중요하다
# 리스트 생성 방식의 두가지 예
marks1 = [['~'] * 3 for n in range(3)] # 연산자 "*" 사용
marks2 = [['~'] * 3] * 3 # Comprehension
print(marks1) # [['~', '~', '~'], ['~', '~', '~'], ['~', '~', '~']]
print(marks2) # [['~', '~', '~'], ['~', '~', '~'], ['~', '~', '~']]
출력결과를 통해 확인한 이 두가지 방법의 결과인 값들은 다를게 없어보이지만, 아래를 통해 명확한 차이를 알 수 있다.
# 수정
marks1[0][1] = 'X'
marks2[0][1] = 'X'
print(marks1) # [['~', 'X', '~'], ['~', '~', '~'], ['~', '~', '~']]
print(marks2) # [['~', 'X', '~'], ['~', 'X', '~'], ['~', 'X', '~']]
# 증명
print([id(i) for i in marks1]) # [1798000212032, 1798000211840, 1798000211776]
print([id(i) for i in marks2]) # [1798000211584, 1798000211584, 1798000211584]
연산자 “*”를 통해 리스트형식의 원소를 생성한 marks2는 해당 원소 리스트들이 같은 값을 가리키고 있었다는 것을 id가 같은 것을 통해 알 수 있었다. 이와 같이 다른 변수에 복사되었지만, 정작 동일한 메모리 주소에 있는 값을 참조하는 형태로 복사된 것을 shallow copy라고 한다. 따라서 marks2의 하나의 원소 리스트 내용을 수정하면 다른 원소 리스트들도 모두 수정되었다.
반면, Comprehension으로 원소 리스트를 생성한 marks1의 경우, 각 원소 리스트가 각각 다른 id를 가리키고 있는 것을 통해 다른 메모리 주소에 복사되며 생성되었다는 것을 알 수 있다. 이처럼 다른 변수에 복사되었고, 그 값 또한 이전 변수의 값과는 다른 메모리 주소에 저장된 동일한 값을 가지도록 복사된 것을 Deep copy라고 한다. 따라서 marks2와 달리 원소 리스트 수정 시, 다른 원소에 해당하는 리스트의 내용은 수정되지 않았다.
Deep, Shallow Copy (3) - sorted vs sort (0) | 2022.04.30 |
---|---|
Deep, Shallow Copy (2) - Mutable vs Immutable (0) | 2022.04.29 |
set, set comprehension, frozen set (0) | 2022.04.27 |
dict와 hash, defaultdict 와 frozendict (0) | 2022.04.26 |
Comprehension (List, Dict), Generator (0) | 2022.04.25 |
댓글 영역