[python] 얕은 복사, 깊은 복사 + 슬라이싱[:]

hodu·2022년 9월 25일
0

python

목록 보기
4/17
post-thumbnail

얕은 복사(Shallow copy)

아주 최소한만 복사한다. 메모리에 생성되는 것이 아닌 '참조'만 복사한 것을 의미한다.
mutable한 객체일 경우에 같은 주소를 바라보게 된다. 슬라이싱과 헷갈릴 수 있으므로 예제를 살펴보자.

a = [1, 2, 3, 4, 5]
b = a

a[1] = 999
print(f'a의 값은 : {a}')
print(f'b의 값은 : {b}')


# 결과값
# a의 값은 : [1, 999, 3, 4, 5]
# b의 값은 : [1, 999, 3, 4, 5]

b = a와 같이 사용할 경우 a의 값을 복사하길 원했는데 '주소값'을 공유하게 된다.

그럼 어떻게 해야할까? 👉 슬라이싱을 이용하면 된다.

슬라이싱을 이용하게 될 경우 '새 리스트'가 만들어지므로 같은 주소를 참조하지 않게 되며 위 문제를 해결할 수 있다.

a = [1, 2, 3, 4, 5]
b = a[:]

a[1] = 999
print(f'a의 값은 : {a}')
print(f'b의 값은 : {b}')


# 결과값
# a의 값은 : [1, 999, 3, 4, 5]
# b의 값은 : [1, 2, 3, 4, 5]

중요한 점은, 슬라이싱으로 만들어낸 배열은 '얕은 복사'라는 것이다.
첫 줄에 얕은 복사를 설명했던 아주 최소한만 복사한다. 메모리에 생성되는 것이 아닌 '주소값'을 복사하여 같은 메모리를 참조하게 된다.
이 설명과 달리 a, b배열은 주소값도 다른 것 같은데 왜 그럴까?🤔

두번째 줄을 잘 읽어보자 mutable한 객체일 경우에 같은 주소를 바라보게 된다.
여기서 mutable은 '값이 변경 될 수 있다'라는 것을 의미한다.

즉 a, b배열의 주소값이 문제가 아니라 어떤 값이 들어있느냐의 문제이다.
예제를 살펴보자.

a = [1, [2, 3], 4, 5]
b = a[:]

a[1][0] = 999

print(f'a의 값은 : {a}')
print(f'b의 값은 : {b}')

처음 예제와 달리 이차원 배열을 만들어보았고 그 안에 있는 값을 수정해보았다.
결과는 다음과 같다.

a의 값은 : [1, [999, 3], 4, 5]
b의 값은 : [1, [999, 3], 4, 5]

슬라이싱을 이용했음에도 불구하고 값이 수정되어 버렸다.

추가) 얕은 복사를 만드는 또다른 방법

  1. copy 사용하기
    b = a.copy()
  2. copy 모듈의 copy 사용하기
    import copy
    b = copy.copy(a)

깊은 복사(Deep copy)

앞서 얕은 복사의 문제점을 해결하기 위해서는 깊은 복사를 이용해야 한다.
깊은 복사는 리스트, 딕셔너리 등 mutable 한 객체를 모두 새로 만들어준다.

import copy

a = [1,[2,3],4,5]
b = copy.deepcopy(a)

a[1][0] = 999

print(f'a의 값은 : {a}')
print(f'b의 값은 : {b}')


# 결과값
# a의 값은 : [1, [999, 3], 4, 5]
# b의 값은 : [1, [2, 3], 4, 5]
profile
안녕 세계!

0개의 댓글