기본 복사는 얕은 복사

매일 공부(ML)·2022년 12월 29일
0

Fluent Python

목록 보기
51/130

객체지향 상용구

객체 참조, 가변성, 재활용

기본 복사는 얕은 복사

#리스트나 대부분의 내장 가변 컬렉션을 복사하는 가장 손 쉬운 방법은 그 자료형 자체의 내장 생성자를 사용

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
profile
성장을 도울 아카이빙 블로그

0개의 댓글