본문 바로가기

Software/Python

파이썬에서의 복사 얕은 복사와 깊은 복사

파이썬은 참 쉬운 언어입니다. 그래서 여러 분야에서 인기를 끌고 있는 거겠죠^^. 그런데 이런 파이썬을 공부하다가 보면 의외의 곳에서 한 번쯤 막히게 됩니다. 바로, 복사(copy)입니다. 무슨 이야기일까요.

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

위 상황이 혹시 눈에 들어 오시나요? a에 [1, 2, 3]을 저장하고, b에 a를 저장하고 난 후, 난 그냥 b의 두번째 숫자를 2에서 0으로 바꾸었는데, a도 따라 바뀌게 되는 기이한 현상입니다.^^

>>> id(a), id(b)
(4431577288, 4431577288)

이유는 메모리상에서 고유한 id를 조회하는 id라는 명령으로 a, b 두 변수를 조회해보면 알 수 있습니다. a와 b라는 변수는 같은 곳을 가르키고 있었던 거죠. 그래서 b를 바꿔도 a가 바뀌게 됩니다. 이런 상황을 벗어나고 싶다면, copy() 옵션을 사용해 주면 됩니다.

>>> b = a.copy()
>>> id(a), id(b)
(4431577288, 4431577544)
>>> b[1] = 10
>>> a
[1, 0, 3]
>>> b
[1, 10, 3]

위 코드에서 처럼 b에 a를 저장할때 copy()를 달아서 보내주면 이런 일을 막을 수 있습니다. 이게 얕은 복사(shallow copy)라고 합니다. 모든 것이 해결된 듯 즐거울뻔~ 했지만^^. 얕은 복사는 그 안의 객체(자식 객체)에는 적용되지 않습니다.

>>> a = [[1, 2], [3, 4], [5, 6]]
>>> b = a.copy()
>>> id(a), id(b)
(4431577352, 4431577288)
>>> b[1]
[3, 4]
>>> b[1][1] = 0
>>> b
[[1, 2], [3, 0], [5, 6]]
>>> a
[[1, 2], [3, 0], [5, 6]]

다시 위 코드를 보면, 분명 첫 번째에서는 id가 달라져 있지만, 그 안에 있는 리스트은 또 동일한 현상이 보입니다.

>>> id(a[1]), id(b[1])
(4431577736, 4431577736)

이렇게 리스트안에 리스트에서는 id가 동일했던 거죠. 이게 얕은 복사입니다. 이것까지 해소 하고 싶다면, copy 모듈을 import하면 됩니다.

>>> import copy
>>> a = [[1, 2], [3, 4], [5, 6]]
>>> b = copy.copy(a)
>>> id(a), id(b)
(4431556232, 4431717128)
>>> id(a[1]), id(b[1])
(4431556104, 4431556104)

copy 모듈의 copy 옵션도 얕은 복사입니다.

>>> b = copy.deepcopy(a)
>>> id(a), id(b)
(4431556232, 4431577288)
>>> id(a[1]), id(b[1])
(4431556104, 4431577608)

deepcopy() 명령이 깊은 복사입니다. 완전히 모두들 id가 달라져 버리는 거죠. 파이썬에서 머신러닝이든 어떤 상황에서 여기까지 고민하게 되는 경우는 별로 없었습니다. 그러나 한번 잘 못 사용하면 곤란하니 자세히 들여다 볼 필요는 있을 겁니다.^^

그럼 즐거운 파이썬 되세요^^

반응형