#리스트나 대부분의 내장 가변 컬렉션을 복사하는 가장 손 쉬운 방법은 그 자료형 자체의 내장 생성자를 사용
l1 = [3.[55,44],(7,8,9)]
l2 = list(l1)
l2
l2 == l1
l2 is l1
생성자나 [:]을 사용하면 얕은 본사를 생성하고, 최상위 컨테이너는 복제하지만 사본은 원래 컨테이너에 들어있던 동일 객체에 대한 참조로 채워지고,모든 항목이 불변형이면 이 방식은 메모리를 절약하며 아무런 문제를 일으키진 않지만 가변 항목이 들어 있을 경우 불쾌한 문제를 야기할 수 있다.
l1 = [3,[66,55,44], (7,8,9)]
l2 = list(l1)
l1.append(100)
l1[1].remove(55)
print('l1:',l1)
print('l2:',l2)
l2[1] += [33,22]
l2[2] += (10,11)
print('l1:',l1)
print('l2:',l2)
얕게 복사한다고 해서 늘 문제가 생기는 것은 아니지만, 내포된 객체의 참조를 공유하지 않도록 깊게 복사할 필요가 있는 경우가 종종 있고 copy 모듈이 제공하는 deepcopy() 함수는 깊은 복사를, copy() 함수는 얕은 복사를 지원한다.
#승객을 승하차하는 버스
class Bus:
def __init__(self, passengers=None):
if passengers is None:
self.passengers = []
else:
self.passengers = list(passenger)
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)
#copy()와 deepcopy()의 비교
import copy
bus1 = Bus(['Alice','Bill','Claire','David'])
bus2 = copy.copy(bus1)
bus3 = copy.deepcopy(bus1)
id(bus1),id(bus2),id(bus3)
bus1.drop('Bill')
bus2.passengers
id(bus1.passengers), id(bus2.passengers), id(bus3.passengers)
bus3.passengers
깊은 사본을 만드는 일은 간단하지 않으므로 객체 안에 순환 참조가 있을 경우 단순한 알고리즘은 무한 루프에 빠질 수 있다. deepcopy() 함수는 순환 참조를 제대로 처리하기 위해서 이미 복사한 객체에 대한 참조 기억을 하고 있다.
#순환 참조 b가 a를 참조한 후에 a의 뒤에 바인딩되는데, deepcopy()는 a를 제대로 복사한다.
a = [10,20]
b = [a,30]
a.append(b)
a
from copy import deepcopy
c = deepcopy(a)
c