본문 바로가기
알고리즘 공부

얕보면 안되는 a = b

by 지금갑시다 2024. 2. 18.

 

제목으로 어그로 조금 끌어봤다ㅎㅎ 

 

내용은 깊은복사와 얕은 복사에 대한 이야기이다.

 

여기 a = [0, 1, 2, 3, 4, 5] 가 있다

이 값을 b 라는 변수에 넣어주고 프린트를 해본다면,

a = [0, 1, 2, 3, 4, 5]
b = a
print(a) # [0, 1, 2, 3, 4, 5]
print(b) # [0, 1, 2, 3, 4, 5]

 

 

위와 같이 나올 것이다. 만약 b에 값을 넣고, a의 0을 100으로 바꿔본다면?

 

a = [0, 1, 2, 3, 4, 5]
b = a
a[0] = 100
print(a) # [100, 1, 2, 3, 4, 5]
print(b) # [100, 1, 2, 3, 4, 5]

 

 

이렇게 a만 값을 바꾸었는데, b도 함께 값이 바뀌게 된다.

이렇게 같은 리스트를 공유하게 되는 것을 얕은 복사라고 한다.

a와 b는 같은 리스트의 메모리 주소를 알고 있는 변수만 복사가 된 것이다.

 

그럼 공유된 값이 아닌 다른 값을 가지고 있게 하려면 어떻게 해주면 되나?

아래와 같이 하면 된다.

 

a = [0, 1, 2, 3, 4, 5]
b = a.copy()
a[0] = 100
print(a) # [100, 1, 2, 3, 4, 5]
print(b) # [0, 1, 2, 3, 4, 5]

 

 

이제 우리가 생각하던 방식대로 나왔다. 

그리고 이렇게 독립적인 값을 갖게 복사를 해주는 경우를 깊은 복사라고 한다.

이렇게 되면 a와 b의 리스트들은 전혀 다른 메모리 공간에 할당되는 것이다.

 

2차원 배열의 경우 어떨까?

 

a = [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
b = a.copy()
a[0][0] = 100
print(a)
print(b)

// 두 결과 모두 아래와 같이 출력된다.
[[100, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]

 

 

 

이 경우엔 copy()를 씀에도 불구하고 왜 얕은 복사가 되었을까? 

이유는 바로 리스트의 모든 깊이의 값을 복사하는 것이 아닌 최상위의 포인팅하는 값만 복사를 해주는 것이기 때문이다.

즉 2차원의 리스트 주소를 포인팅하고 있는 변수만 복사된 것이기 때문이다.

 

이를 해결하기 위해서는 아래와 같이 2가지의 방법이 있다.

1. copy 모듈을 활용한 깊은 복사를 사용하기

2. b의 모든 값에 a의 값 직접 대입하는 방법 (리스트를 대입할때와 달리 값을 직접 넣으면 새로운 값이 할당된다)

 

 

# 1번 방법
import copy
a = [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
b = copy.deepcopy(a)
a[0][0] = 100
print(a) # [[100, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
print(b) # [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]

# 2번 방법
a = [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
b = [[0 for i in range(6)] for _ in range(2)]

for i in range(2):
	for j in range(6):
    	b[i][j] = a[i][j]

a[0][0] = 100
print(a) # [[100, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]
print(b) # [[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]]

 

 

이렇게 지금 내가 얕은 복사를 사용하고 있는지 깊은 복사를 사용하고 있는지 자세히 파악하고 있는 것은

예기치 못한 결과가 나왔을 때 빠르게 판단할 수 있는 도움을 준다 ㅎ

'알고리즘 공부' 카테고리의 다른 글

Greedy라는 방법론  (0) 2024.03.19
중등수학으로 2차원 배열 방향 전환 이해하기  (3) 2024.01.03