파이썬 - 얕은 복사 / 깊은 복사

jaybon·2022년 10월 15일
0

파이썬

목록 보기
13/20
post-thumbnail

얕은 복사

객체의 레퍼런스만 복사하는 방법이다.

감자라고 적힌 상자가 있다.

안에는 각 감자가 있는 곳을 적어 놓은 쪽지가 있다.

감자라고 적힌 상자에다가 potato라고 적은 것과 마찬가지.

즉 동일한 상자인 것이다.

1

감자 = [["감자1"], ["감자2"], ["감자3"]]

print(id(감자))

# 2751032212672

print(id(감자[0]))

# 2751032856464

potato = 감자

print(id(potato))

# 2751032212672

print(id(potato[0]))

# 2751032856464

# potato 상자 안의 쪽지 내용을 바꿔보자.
potato[0][0] = "썩은감자"

# 감자 상자 안이 바뀌었다.
print(감자)
# [['썩은감자'], ['감자2'], ['감자3']]

2

리스트 슬라이싱 방식으로 복사를 해보았다.

상자는 바뀐것 같은데 내부의 감자위치 쪽지는 같은 것들이다.

potato 상자의 첫번째 쪽지를 수정해보자.

감자 상자의 첫번째 쪽지의 내용이 바뀌어 있다.

감자 = [["감자1"], ["감자2"], ["감자3"]]

print(id(감자))

# 2751032212672

print(id(감자[0]))

# 2751032856464

# 리스트 슬라이싱
potato = 감자[:]

print(id(potato))

# 2751032198016

print(id(potato[0]))

# 2751032856464

# potato 상자 안의 쪽지 내용을 바꿔보자.
potato[0][0] = "썩은감자"

# 감자 상자 안이 또 바뀌었다.
print(감자)
# [['썩은감자'], ['감자2'], ['감자3']]

문제점

다른 용도로 사용하기 위해 복사를 하였는데, 복사한 것의 내용을 바꿨더니 복사했던 물건까지 바뀌어있다니?

예를들어 텍스트파일 test.txt를 복사하여 test_copy.txt를 만들어서 내용을 적었더니, test.txt파일이 바뀌어 있다는 말이나 마찬가지이다.


깊은 복사

완전히 다른 객체를 만들어 버리고 싶다.

1. deepcopy 라이브러리

파이썬의 표준 라이브러리 중 하나인 deepcopy를 사용해보자.

from copy import deepcopy

감자 = [["감자1"], ["감자2"], ["감자3"]]

print(id(감자))

# 2009223428032

print(id(감자[0]))

# 2009223566400

potato = deepcopy(감자)

print(id(potato))

# 2009223428288

print(id(potato[0]))

# 2009223429952

# potato 상자 안의 쪽지 내용을 바꿔보자
potato[0][0] = "썩은감자"

# 감자 상자 안은 그대로이다!
print(감자)
# [['감자1'], ['감자2'], ['감자3']]

하지만 깊은 복사는 매우 느리다.

거대한 시스템이나 게임 등을 만들면 객체가 매우 많아지므로 깊은 복사가 느리면 게임도 느려지게 된다.

다른 방법을 찾아보자.

2. json 라이브러리

마찬가지로 python의 표준 라이브러리인 json이다.

import json

감자 = [["감자1"], ["감자2"], ["감자3"]]

potato = json.loads(json.dumps(감자))

print(potato)

deepcopy보다 매우 빠른 줄 알았는데,
객체가 단순하고 양이 적으면 json이 빠르나,
객체가 복잡하고 양이 많아지면 deepcopy가 더 빠르다.

더 좋은 방법이 없을까?

3. marshal 라이브러리

마찬가지로 python의 표준 라이브러리인 marshal이다.

어떤 상황에서도 가장 빠르다.
속도 체크는 아래의 참고 자료의 스택 오버 플로우로 가서 확인해보자.

import marshal

감자 = [["감자1"], ["감자2"], ["감자3"]]

potato = marshal.loads(marshal.dumps(감자))

marshal이란?

파이썬 라이브러리 marshal을 뜻하기 보다는 사전적인 의미로 알아보자.

마샬링이라고 하는데, 보통 직렬화를 뜻한다.
직렬화란 객체를 문자열로 만드는 행위인데,
단순히 문자열로 만드는 것이 아니라 다시 객체로 만들 수 있는 문자열로 바꾸는 것이다.

marshal.dumps -> 직렬화
marshal.loads -> 역직렬화

다시 객체로 만드는 것을 역직렬화라고 한다.

위의 json 라이브러리도 직렬화와 역직렬화를 담당한다.

실제 자바스크립트에서도 JSON객체가 담당한다.

참고 자료

스택 오버 플로우
https://stackoverflow.com/questions/24756712/deepcopy-is-extremely-slow

https://crackerjacks.tistory.com/14

profile
티스토리 블로그 https://ondolroom.tistory.com/

0개의 댓글