[Python]얕은 복사, 깊은 복사

Hyemin_12·2022년 5월 12일

Python

목록 보기
3/3
post-thumbnail

얕은 복사, 깊은 복사

<얕은 복사와 깊은 복사를 리스트를 이용하여 알아보기>

얕은 복사

=을 사용하는 얕은 복사

  • 리스트와 복사된 리스트 모두 동일한 주소를 참조한다. 즉, 주소(참조)를 복사한다.
# =을 이용한 얕은 복사
# 주소 동일
arr1 = [1, 2, 3]
arr2 = arr1 # 얕은 복사

print(f"arr1 : {arr1} \t 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2} \t 주소 : {hex(id(arr2))}")
# 출력 결과 -> arr1과 arr2의 주소가 같다

arr1.append(4) # arr1에 값을 추가

print(f"arr1 : {arr1} \t 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2} \t 주소 : {hex(id(arr2))}")
# 출력 결과 -> arr1과 arr2의 주소가 같다
# 주소(참조)만 복사한 것이기 때문에 원본의 내용이 바뀌면 같이 바뀐다

[:]을 사용하는 얕은 복사

  • mutable 안에 mutable이 들어 있을 때 그 mutable에 대해 얕은 복사를 사용한다.
  • 다른 주소를 참조하기에 얼핏 보면 깊은 복사로 오해할 수 있지만 내부 주소는 동일한 주소를 참조하기 때문에 얕은 복사이다.
# [:]을 이용한 얕은 복사
# 주소 다름, 내부 주소 동일
arr1 = [4, 5, 6, [2, 4, 8]] # [2, 4, 8] -> 내부 리스트
arr2 = arr1[:] # 얕은 복사

print(f"arr1 : {arr1}, 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2}, 주소 : {hex(id(arr2))}")
# 출력 결과 -> arr1과 arr2의 주소가 다르다

arr1.append(4) # arr1에 값 추가
arr2.append(22) # arr2에 값 추가

print(f"arr1 : {arr1}, 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2}, 주소 : {hex(id(arr2))}")
# 출력 결과 -> arr1에 4가 추가되고, arr2에 22가 추가되며 arr1과 arr2의 주소가 다르다
# 이것 때문에 깊은 복사로 생각할 수 있음!

# 리스트 안에 있는 리스트, arr[3](= [2, 4, 8])
print(f"arr1[3] : {arr1[3]}, 주소 : {hex(id(arr1[3]))}")
print(f"arr2[3] : {arr2[3]}, 주소 : {hex(id(arr2[3]))}")
# 출력 결과 -> arr1[3]과 arr2[3]의 주소가 같다
# [:]은 내부 리스트에서 동일한 주소를 참조하기 때문이다

arr1[3].append(99) # 내부 리스트 arr[3]에 값 추가

print(f"arr1[3] : {arr1[3]}, 주소 : {hex(id(arr1[3]))}")
print(f"arr2[3] : {arr2[3]}, 주소 : {hex(id(arr2[3]))}")
# 출력 결과 -> arr1[3]과 arr2[3]에 99가 추가되고, arr1[3]과 arr2[3]의 주소가 같다
# 내부 리스트는 동일한 주소를 참조하므로 둘 다 값이 바뀐다

copy 메소드 사용한 얕은 복사

  • [:]과 마찬가지로 다른 주소를 참조하지만 내부 리스트는 동일한 주소를 참조한다.
# copy 메소드 이용한 얕은 복사
# 주소 다름, 내부 주소 동일
arr1 = [4, 5, 6, [2, 4, 8]] # [2, 4, 8] -> 내부 리스트
arr2 = arr1.copy() # 얕은 복사

print(f"arr1 : {arr1}, 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2}, 주소 : {hex(id(arr2))}") 
# 출력 결과 -> arr1과 arr2의 주소가 다르다

arr2.append(22) # arr2에 값 추가

print(f"arr1 : {arr1}, 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2}, 주소 : {hex(id(arr2))}") 
# 출력 결과 -> arr2에만 22가 추가되고, 주소가 다르다
# 이것 때문에 깊은 복사로 생각할 수 있음!

# 리스트 안에 있는 리스트
print(f"arr1[3] : {arr1[3]}, 주소 : {hex(id(arr1[3]))}")
print(f"arr2[3] : {arr2[3]}, 주소 : {hex(id(arr2[3]))}") 
# 출력 결과 -> arr1[3]과 arr2[3]의 주소가 같다

arr1[3].append(99) # 내부 리스트 arr[3]에 값 추가

print(f"arr1[3] : {arr1[3]}, 주소 : {hex(id(arr1[3]))}")
print(f"arr2[3] : {arr2[3]}, 주소 : {hex(id(arr2[3]))}") 
# 출력 결과 -> arr1[3]과 arr2[3]에 99가 추가되고, arr1[3]과 arr2[3]의 주소가 같다

copy 모듈의 copy 함수를 사용한 얕은 복사

  • [:]과 마찬가지로 다른 주소를 참조하지만 내부 리스트는 동일한 주소를 참조한다.
# copy 모듈의 copy 함수를 이용한 얕은 복사
# 주소 다름, 내부 주소 동일
import copy # 요거 써줘야 함! 크크
arr1 = [4, 5, 6, [2, 4, 8]]
arr2 = copy.copy(arr1) # 얕은 복사

print(f"arr1 : {arr1}, 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2}, 주소 : {hex(id(arr2))}")
# 출력 결과 -> arr1과 arr2의 주소가 다르다

arr2.append(22) # arr2에 값 추가

print(f"arr1 : {arr1}, 주소 : {hex(id(arr1))}")
print(f"arr2 : {arr2}, 주소 : {hex(id(arr2))}")
# 출력 결과 -> arr2에만 22가 추가되고, 주소가 다르다
# 이것 때문에 깊은 복사로 생각할 수 있음!

# 리스트 안에 있는 리스트
print(f"arr1[3] : {arr1[3]}, 주소 : {hex(id(arr1[3]))}")
print(f"arr2[3] : {arr2[3]}, 주소 : {hex(id(arr2[3]))}")
# 출력 결과 -> arr1[3]과 arr2[3]의 주소가 같다

arr1[3].append(99) # 내부 리스트 arr[3]에 값 추가

print(f"arr1[3] : {arr1[3]}, 주소 : {hex(id(arr1[3]))}")
print(f"arr2[3] : {arr2[3]}, 주소 : {hex(id(arr2[3]))}") 
# 출력 결과 -> arr1[3]과 arr2[3]에 99가 추가되고, arr1[3]과 arr2[3]의 주소가 같다

깊은 복사

  • copy 모듈의 deepcopy를 이용하여 복사한다.
  • 값만 복사하고 서로 다른 주소를 참조한다.
    -> 내부 리스트도 다른 주소를 참조한다.
# copy 모듈의 deepcopy를 이용한 깊은 복사
# 값만 복사, 객체 공유X
import copy # copy 모듈 불러오기 꼭 써야함!
arr1 = [1, 2, [99, 88, 77], 3]
arr2 = copy.deepcopy(arr1) # 깊은 복사

print(f"arr1 : {arr1}, address : {hex(id(arr1))}")
print(f"arr2 : {arr2}, address : {hex(id(arr2))}")
# 출력 결과 -> arr1과 arr2의 주소가 다르다
 
arr1.append(0) # arr1에 값 추가

print(f"arr1 : {arr1}, address : {hex(id(arr1))}")
print(f"arr2 : {arr2}, address : {hex(id(arr2))}")
# 출력 결과 -> arr1에 0이 추가되고, arr1과 arr2의 주소가 다르다

# 리스트 내부에 리스트 추가
print(f"arr1[2] : {arr1[2]}, address : {hex(id(arr1[2]))}")
print(f"arr2[2] : {arr2[2]}, address : {hex(id(arr2[2]))}") 
# 출력 결과 -> arr1과 arr2의 주소가 다르다(깊은 복사이기 때문!)

arr1[2].append(10) # 내부 리스트 arr1[2]에 값 추가

print(f"arr1[2] : {arr1[2]}, address : {hex(id(arr1[2]))}")
print(f"arr2[2] : {arr2[2]}, address : {hex(id(arr2[2]))}") 
# 출력 결과 -> arr1[2]에 10이 추가되고, arr1과 arr2의 주소가 다르다
profile
개발 블로그🌱

0개의 댓글