copy — 얕은 복사와 깊은 복사 연산
copy — 얕은 복사와 깊은 복사 연산
Python에서 할당문은 객체를 복사하지 않고 대상과 객체 사이의 바인딩만 만듭니다. 가변형이거나 가변 항목을 담고 있는 컬렉션의 경우, 한 복사본을 바꿔도 다른 복사본이 바뀌지 않도록 복사가 필요할 때가 있습니다. 이 모듈은 일반적인 얕은 복사와 깊은 복사 연산을 제공합니다.
본문
인터페이스 요약:
copy.copy(obj)—obj의 얕은 복사본을 반환합니다.copy.deepcopy(obj[, memo])—obj의 깊은 복사본을 반환합니다.copy.replace(obj, /, **changes)—obj와 같은 타입의 새 객체를 만들되, 필드를changes의 값으로 교체합니다 (3.13에서 추가).copy.Error— 모듈 특유의 오류에 대해 발생하는 예외입니다.
얕은 복사와 깊은 복사의 차이는 복합 객체(리스트나 클래스 인스턴스처럼 다른 객체를 담고 있는 객체)에만 관련됩니다:
- 얕은 복사는 새 복합 객체를 만들고, 가능한 범위에서 원본에 있던 객체들에 대한 참조를 그 안에 넣습니다.
- 깊은 복사는 새 복합 객체를 만들고, 원본에 있던 객체들의 복사본을 재귀적으로 넣습니다.
깊은 복사에는 얕은 복사에는 없는 두 가지 문제가 자주 발생합니다:
- 재귀 객체(직간접적으로 자신에 대한 참조를 담고 있는 복합 객체)는 재귀 루프를 일으킬 수 있습니다.
- 깊은 복사는 모든 것을 복사하기 때문에, 복사본들 사이에 공유하려던 데이터까지 지나치게 많이 복사할 수 있습니다.
deepcopy() 함수는 현재 복사 과정에서 이미 복사된 객체들의 memo 딕셔너리를 유지하고, 사용자 정의 클래스가 복사 연산이나 복사할 구성 요소 집합을 오버라이드하게 함으로써 이 문제들을 피합니다.
이 모듈은 모듈, 메서드, 스택 트레이스, 스택 프레임, 파일, 소켓, 윈도우 같은 타입은 복사하지 않습니다. 함수와 클래스는 (얕든 깊든) 복사하되 원본 객체를 그대로 반환합니다. 이는 pickle 모듈이 이들을 다루는 방식과 호환됩니다.
많은 컬렉션의 얕은 복사는 해당 copy() 메서드(list.copy(), dict.copy(), set.copy() 등)나 시퀀스 전체의 슬라이스(sequence[:])로 만들 수 있습니다. 하지만 이 메서드들과 슬라이스는 서브클래스 인스턴스를 복사할 때 기본 타입의 인스턴스를 만들 수 있는 반면, copy.copy()는 보통 같은 타입의 인스턴스를 반환합니다.
클래스는 pickling을 제어할 때와 같은 인터페이스로 복사를 제어할 수 있습니다. copy 모듈은 copyreg 모듈에 등록된 pickle 함수를 사용합니다. 클래스가 자신만의 복사 구현을 정의하려면 __copy__(self)와 __deepcopy__(self, memo) 특별 메서드를 정의하면 됩니다. __deepcopy__ 구현이 구성 요소를 깊은 복사해야 한다면, 해당 구성 요소를 첫 번째 인자로, memo 딕셔너리를 두 번째 인자로 하여 deepcopy() 함수를 호출해야 합니다. memo 딕셔너리는 불투명한 객체로 취급해야 합니다.
copy.replace() 함수는 copy()와 deepcopy()보다 제한적이며, namedtuple()로 만든 네임드 튜플, dataclasses, 그리고 __replace__(self, /, **changes) 메서드를 정의하는 다른 클래스만 지원합니다. __replace__ 메서드는 같은 타입의 새 객체를 만들되 필드를 changes의 값으로 교체해야 합니다 (3.13에서 추가).