파이썬에서는 배열을 선언할 때 여러가지 방법들이 있다.

 

list_1 = []
list_2 = [] * 5
list_3 = [] for _ in range(5)

등등 여러가지가 있는데, 그중에서도 오늘은 for 문과 * 연산자를 이용한 배열 선언의 차이에 대해서 적어보고자 한다.

 

2차원 배열을 선언할 때는 3가지 방법을 쓸 수 있다.

 

 

첫 번째로 빈 리스트 생성 후 append로 더하기이다.

# 아예 빈 리스트를 생성 후 append로 더하기

list_1 = []
list_1.append([0, 0, 0])

print(list_1)

# [[0, 0, 0]]

다만 이 방법은 추후 코드를 통해서 append 해야하기 때문에, 실질적으로 append 하기 전까진 1차원 배열이라고 할 수 있다.

따라서 다음과 같은 코드를 실행하는 데 문제가 발생한다.

# Index Error 발생

list_1 = []

# IndexError: list index out of range
print(list_1[0][1])

list_1.append([0, 0, 0])

따라서 위와 같은 문제를 해결하기 위해 2가지 방법을 더 생각해 볼 수 있다.

 

 

두 번째로 * 연산자를 이용한 선언이다.

# * 연산자를 이용한 선언

list_1 = [[0] * 3] * 5

print(list_1[0][1])

list_1.append([1, 1, 1])

# 0

 

 

세 번째로는 for문을 이용한 선언이다.

# for문을 이용한 선언

list_1 = [[0 for col in range(3)] for row in range(5)]

print(list_1[0][1])

list_1.append([1, 1, 1])

# 0

 

두 번째와 세 번째를 모두 실행해보면 같은 결과를 출력하는 걸 볼 수 있다.

그렇기에 둘 다 같은 거라는 생각이 들 수 있다.

하지만 둘은 엄연히 다르다.

 

 

이걸 설명하기 위해서는 깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy)에 대해서 알아야한다.

우선 깊은 복사는 변수나 객체가 가지고 있는 값을 그대로 복사하여, 다른 변수나 객체가 동일한 값을 가지게 하는 것이고,

얕은 복사는 변수나 객체를 참조하는 것이다.

 

즉 깊은 복사는 원본 객체와 복사된 객체는 별개의 객체이지만, 얕은 복사는 복사된 객체가 원본 객체를 참조하기 때문에 둘간의 연결성이 있다.

 

# 세로 길이가 3, 가로 길이가 2인 행렬이 있다고 했을 때,
# 이를 2차원 배열로 바꾸는 2가지 방법의 차이점

# 얕은 복사
list_1 = [[False] * 2] * 3
# 깊은 복사
list_2 = [[False for col in range(2)] for row in range(3)]

print(list_1)
print(list_2)
# [[False, False], [False, False], [False, False]]
# [[False, False], [False, False], [False, False]]

list_1[0][0] = True
list_2[1][1] = True

print(list_1)
print(list_2)
# [[True, False], [True, False], [True, False]]
# [[False, False], [False, True], [False, False]]

위와 같이 list_1은 [False] * 2로 각각의 요소들을 얕은 복사를 했기에,

[0][0]뿐만 아니라 [1][0], [2][0]까지도 값이 변경된 것을 확인 할 수 있다.

 

반대로 list_2는 for문을 통한 깊은 복사를 했기에,

[1][1] 요소만 변경되고, 나머지 요소에는 영향을 주지 않은 것을 볼 수 있다.

 

 

간혹 함수에 매개변수 값을 전달할 때 자주 나오는 pass by reference, pass by value도 이와 비슷한 맥락이라 볼 수 있다.

둘이 완전히 동일하진 않지만, 값을 전달 할 것인가, 참조할 것인가의 차이인 점에서는 같다.

 

 

 

파이썬에 익숙하지 않다보니, 얕은 복사인지도 모르고 쓰다가 수십 분을 허비한 경험으로 글을 쓰게 되었다.

다들 쉽다고 하는데, 왜 나는 이렇게 파이썬이 어려운지 잘 모르겠다

차근차근 시간을 두고 익혀봐야겠다.

'Language > Python' 카테고리의 다른 글

[Python] List Slicing  (0) 2022.08.09

+ Recent posts