상세 컨텐츠

본문 제목

Deep, Shallow Copy (1) - 반복을 통한 List 생성 2가지 비교

개발/python-심화(Advanced)

by Matthew0633 2022. 4. 28. 23:34

본문

List 생성, 복사, 수정을 할 때, Deep Copy와 Shallow Copy가 일어나는 문법들을 구분하여 사용하지 않는다면, 내가 다루는 자료의 내용이 원치 않는 결과로 이어질 수 있다. Mutable한 List 생성, 복사, 수정을 할 수 있는 문법들과, 이들이 return하는 결과값을 정확히 알고 정리하는 것이 중요하다

 

반복을 활용한 List 생성 ( 연산자 “*” 사용 vs Comprehension)

  • 굳이 이중리스트 값으로 예를 든 이유는 원소로 list 형식을 사용했을 때 mutable하여 수정이 가능하고, 이를 통해 차이를 살펴볼 수 있기 때문이다. 따라서 예시를 볼 때, 이중리스트에 큰 의미를 두지 않아도 되겠다.
  • List를 생성하고 원소들을 반복문을 통해서 초기화하고자 할 때 두가지 방식이 있다. 연산자 “*”를 사용하는 방식과 Comprehension을 사용하는 방식이다.
# 리스트 생성 방식의 두가지 예
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와 달리 원소 리스트 수정 시, 다른 원소에 해당하는 리스트의 내용은 수정되지 않았다.

관련글 더보기

댓글 영역