매일을 설렘으로

[Python] List - 얇은 복사 (shallow copy), 깊은 복사 (deep copy) 본문

카테고리 없음

[Python] List - 얇은 복사 (shallow copy), 깊은 복사 (deep copy)

하루설렘 2021. 11. 10. 10:10

백준 2468번 문제를 풀다보니 2D 리스트를 아래와 같이 선언을 해주고 특정 위치에만 값을 주었는데 

알수없는 에러가 발생했다. 알고보니 아래와 같이 list를 선언해주면 list의 얇은 복사가 되기에 원소값을 변경해주면 다른 행의 리스트도 동일하게 변경된다. 리스트 자료구조에 대해서 알아봐야겠다. 

실행문

 

특정값 대입후 실행문

 

1. 파이썬은 리스트를 저장할 때 값 자체가 아니라, 값이 위치한 메모리 주소(reference)를 저장합니다.

    : a = [0, 1, 2] 라는 리스트를 선언하면 a에는 리스트의 주소를 저장한다. 그리고 리스트 내 a[0], a[1]에도 그 숫자객체

     가 저장된 주소를 저장한다. 

 

 

1. 얇은 복사 (shallow copy)

  • list_b = list_a
  • list_b = list_a[:]

둘다 모두 얇은 복사 개념이지만, 첫번째의 경우, list_a의 주소값을 그대로 list_b에 저장한다. 

>>> a = [0, 1, 2]
>>> b = a

>>> b
[0, 1, 2]

>>> id(a), id(b)
(1851630156992, 1851630156992)
//list를 가리키는 id 값이 동일하다.

>>> id(a[0]), id(a[0])
(140706449073936, 140706449073936)
//list 내부 원소의 id 값 역시 동일하다.

list_b는 list_a의 주소값을 그대로 사용하기에 a가 변경되면 b값도 동일하게 따라간다.

하지만, 리스트안에 리스트 mutable객체 안에 mutable객체인 경우 문제가 됩니다.

>>> a = [0, 1, 2]
>>> b = a
>>> a.append(5)
>>> a
[0, 1, 2, 5]
>>> b
[0, 1, 2, 5]


>>> a = [7, 2, 3]
>>> a
[7, 2, 3]
>>> b
[0, 1, 2, 5]

반면, 두번째의 경우, list_a 주소와 별개로 list_b를 새로운 주소를 할당하지만, list 내부 원소의 주소는 동일하다. 

>>> a = [0, 1, 2]
>>> b = a[:]
>>>
>>> id(a), id(b)
(1851630466240, 1851630468416)

>>> id(a[0]), id(b[0])
(140706449073936, 140706449073936)

>>> b[0] = 5
>>> id(a[0]), id(b[0])
(140706449073936, 140706449074096)
  • 리스트안에 리스트 mutable객체 안에 mutable객체인 경우 문제가 됩니다.
>>> a = [[0,1], [2,3]]
>>> b= a[:]
>>> a
[[0, 1], [2, 3]]
>>> b
[[0, 1], [2, 3]]
>>>
>>> a[1][1] = 9
>>> b
[[0, 1], [2, 9]]
//뮤터블안에 뮤터블의 원소를 변경하면 a따라 b도 변경된다.

2. 깊은 복사 (deep copy)

  • 깊은 복사는 내부에 객체들까지 모두 새롭게 copy 된다.
  • copy.deepcopy메소드가 해결해준다. 
>>> import copy 
>>> a = [[1,2],[3,4]] 
>>> b = copy.deepcopy(a) 
>>> a[1].append(5) 
>>> a [[1, 2], [3, 4, 5]] 
>>> b [[1, 2], [3, 4]]