written by yechoi

파이썬 2차원 배열 선언, 이 방법은 피하세요! 본문

Born 2 Code/Python

파이썬 2차원 배열 선언, 이 방법은 피하세요!

yechoi 2020. 12. 1. 18:36
반응형

2차원 배열을 선언해야 하는 백준 BFS 문제를 풀고 있었다. 한 블로그에서 2차원 배열을 선언하는 여러 방법을 올려놨길래, 그 중 내 마음에 제일 드는 짧은 코드를 골라 썼다. 그런데 아무리 봐도 bfs 로직은 틀린 게 없는데, 원하는 답이 안나오는 것...! 한 줄씩 고쳐가면서 확인하다가 찾아냈다. 이유는 2차원 배열 선언 방법이 잘못 됐던 것.

 

다 읽기 귀찮으신 분들을 위해, 2차원 배열 초기화에 가장 적합한 코드를 미리 써둡니다.

# COLUM : 가로 길이
# ROW : 세로 길이
board = [[0 for i in range(COLUM)] for j in range(ROW)] 

 

 

대입연산에서 말썽부리는 * 연산자 활용 초기화

내가 택했던 방식은 * 연산자를 활용하는 방법이었다.

board = [[0] * 4] * 4
for i in range(4):
  print(board[i])

 

초기화 결과는 예쁘게 나온다.

[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]

 

문제는 대입 연산을 진행할 때 발생한다. 여기서 [0,0](1행 1열)을 1로 바꿔보자. 

board[0][0] = 1
for i in range(4):
  print(board[i])

 

그 결과는...?

[1, 0, 0, 0]
[1, 0, 0, 0]
[1, 0, 0, 0]
[1, 0, 0, 0]

 

 

 

롸...? 얼탱이가 없음 ㅋㅋㅋㅋ 왜 모든 1열이 1로 바뀐 건데....?

 

 

문제는 얕은 복사야

문제는 파이썬이 * 연산자로 초기화를 할 때 값을 각각 할당하는 게 아니고, 하나의 객체를 생성해 놓곤 모두가 이를 가리키는 '얕은 복사'를 진행한다는 데서 발생한다.

 

 

[0] * 4는 이런 방식으로 동작합니다

 

 

[0]  * 4는 이렇게 동작한다. 하나의 0 정수형 객체를 생성하고, 배열의 각 요소들이 이를 가리킨다. 0이 4개가 아닌 1개만 생성되는 것. 

 

 

[[0] * 4] * 4 는 이런 방식으로 동작합니다

 

 

먼저 첫번째 배열이 생성되고 나면, 두번째 - 세번째 - 네번째 배열이 모두 처음 생성된 배열을 가리킨다. 1차원 배열은 네 개가 아닌 하나 생긴거고, 모두가 이를 가리키고 있다고 생각하면 되겠다.  

 

 

배열의 값을 바꿔 봅시다

 

 

이제 그럼 배열의 값을 바꿔보자. 일단 board[0][0] = 1 을 하면 board[0][0]은 0을 가리키고 있다가, 새로 정수 객체 1을 생성하고 이를 가리킨다. 여기까진 의도한 대로 바뀌었다. 

 

 

 

문제는 다른 배열들이 첫번째 배열을 가리키고 있다는 것이다. board[1][0], board[2][0], board[3][0]도 모두 결국 board[0][0]을 가리키고 있으므로, 이 값들 모두 새로 생성된 정수 객체 1을 가리킨다. 

 

 

복사는 for 문을 활용합시다

얕은 복사를 피하려면 for문을 활용하는 게 좋다. 도입부에 써놓은 열 복사, 행 복사 모두 for 문으로 해준다면 얕은 복사를 완전히 피할 수 있겠다. 그렇지 않더라도 열 복사가 아닌 행 복사만 *연산자가 아닌 for문을 활용하더라도 이런 문제는 피할 수 있다.

board = [[0] * 4 for _ in range(4)]
board[1][2] = 1
for i in range(4):
  print(board[i])

 

이 코드는 초기화와 대입 연산 모두 아름답게 의도한 대로 나온다.

# 초기화 결과
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]

# board[1][2] = 1 결과
[0, 0, 0, 0]
[0, 0, 1, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]

 

 

* 출처 : 

Python | Using 2D arrays/lists the right way - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

반응형