최근 list를 초기화하는 신박한(?) 방법을 알게되어 자주 쓰고 있었는데,
생각지 못한 문제가 생겨 몇 분이나(...) 삽질을 하다가 알게 되어 정리해보려고 합니다.
(1) * 를 이용해 간단하게 list 생성하기
보통 백준에서 python 숏코딩 답안을 보면,
visit = [n * [0] for _ in range(n)]
이런식으로 * 를 사용해 list를 만드는 것을 자주 볼 수 있습니다.
실제로 아래 코드를 실행해보면,
test_arr = [0]*3
print(test_arr)
>> [0, 0, 0]
이렇게 출력되는 것을 알 수 있습니다.
마찬가지로 2차원 배열을 생성해볼 수도 있습니다.
test_arr = [[0]*3]*3
print(test_arr)
>> [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
이렇게 2차원 배열도 생성해 보았습니다.
(2) 주의할 점
생성까지는 문제가 없지만.. 문제는 이 방법으로 만든 2차원 이상의 list 값을 변경할 때 생겼습니다.
i=1, j=1의 값만을 변경하려는 상황임을 가정해봅시다.
[[0, 0, 0], [0, 0, 0], [0, 0, 0]] -> [[0, 0, 0], [0, 2, 0], [0, 0, 0]]
아래 코드를 이용해 보통의 list 값을 변경하듯이 해보면,
test_arr = [[0]*3]*3
test_arr[1][1] = 2 # 값 수정
print(test_arr)
>> [[0, 2, 0], [0, 2, 0], [0, 2, 0]]
위와 같이 신기하게(?) 다 같이 변경되어 있습니다.
왜 이렇게 되는 건지 너무 궁금해서 바로 python 공식 문서를 찾아보았습니다.
이렇게 만들어 낸 list들은 한 list만을 reference하고 있어서, 어떤 list 내용이 바뀌면 다 같이 바뀌게 되는 것입니다.
실제로 아래 코드를 실행해보면,
test_arr = [[0]*3]*3
test_arr[1] = [2,2,2] # 1번 list는 새로 정의해 줌
test_arr[2][1] = 2 # 0번, 2번 list는 아직 reference 중
print(test_arr)
>> [[0, 2, 0], [2, 2, 2], [0, 2, 0]]
잔~ 이렇게 1번 list는 새로운 list가 되었고 0번 2번 list끼리는 또 같이 바뀐 것을 알 수 있습니다.
(3) 결론
- 1차원 list는 *을 이용해 자유롭게 만들어도 될 것 같다.
- 2차원부터는 그냥 안전하게 for문을 이용해 만들자.
anjeon_arr1 = [[0 for _ in range(n)] for _ in range(n)]
anjeon_arr2 = [n * [0] for _ in range(n)]