객체의 레퍼런스만 복사하는 방법이다.
감자라고 적힌 상자가 있다.
안에는 각 감자가 있는 곳을 적어 놓은 쪽지가 있다.
감자라고 적힌 상자에다가 potato라고 적은 것과 마찬가지.
즉 동일한 상자인 것이다.
감자 = [["감자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']]
리스트 슬라이싱 방식으로 복사를 해보았다.
상자는 바뀐것 같은데 내부의 감자위치 쪽지는 같은 것들이다.
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파일이 바뀌어 있다는 말이나 마찬가지이다.
완전히 다른 객체를 만들어 버리고 싶다.
파이썬의 표준 라이브러리 중 하나인 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']]
하지만 깊은 복사는 매우 느리다.
거대한 시스템이나 게임 등을 만들면 객체가 매우 많아지므로 깊은 복사가 느리면 게임도 느려지게 된다.
다른 방법을 찾아보자.
마찬가지로 python의 표준 라이브러리인 json이다.
import json
감자 = [["감자1"], ["감자2"], ["감자3"]]
potato = json.loads(json.dumps(감자))
print(potato)
deepcopy보다 매우 빠른 줄 알았는데,
객체가 단순하고 양이 적으면 json이 빠르나,
객체가 복잡하고 양이 많아지면 deepcopy가 더 빠르다.
더 좋은 방법이 없을까?
마찬가지로 python의 표준 라이브러리인 marshal이다.
어떤 상황에서도 가장 빠르다.
속도 체크는 아래의 참고 자료의 스택 오버 플로우로 가서 확인해보자.
import marshal
감자 = [["감자1"], ["감자2"], ["감자3"]]
potato = marshal.loads(marshal.dumps(감자))
파이썬 라이브러리 marshal을 뜻하기 보다는 사전적인 의미로 알아보자.
마샬링이라고 하는데, 보통 직렬화를 뜻한다.
직렬화란 객체를 문자열로 만드는 행위인데,
단순히 문자열로 만드는 것이 아니라 다시 객체로 만들 수 있는 문자열로 바꾸는 것이다.
marshal.dumps -> 직렬화
marshal.loads -> 역직렬화
다시 객체로 만드는 것을 역직렬화라고 한다.
위의 json 라이브러리도 직렬화와 역직렬화를 담당한다.
실제 자바스크립트에서도 JSON객체가 담당한다.
스택 오버 플로우
https://stackoverflow.com/questions/24756712/deepcopy-is-extremely-slow