내 시간을 낭비한 그 한 가지 Python 리스트 버그 😅
Source: Dev.to
문제점
최근 2‑D 리스트가 필요한 문제를 풀다가 이상한 파이썬 버그를 마주했습니다.
코드는 올바르게 보였지만 출력은 완전히 틀렸습니다. 원인은 다음 한 줄이었습니다:
index = [[0, 0]] * n
파이썬을 어느 정도 써본 사람이라면 이것이 n개의 행을 각각 [0, 0]으로 만들 것이라고 기대할 수 있습니다. 예를 들어:
[
[0, 0],
[0, 0],
[0, 0]
]
왜 *이 여기서는 안 되는가
파이썬은 n개의 별도 내부 리스트를 만들지 않습니다. 하나의 리스트 [0, 0]를 만들고 이를 n번 참조합니다. 모든 행이 같은 객체를 가리키게 됩니다.
증명
index = [[0, 0]] * 3
index[0][0] = 7
print(index)
출력
[[7, 0], [7, 0], [7, 0]]
하나의 값을 바꾸면 모든 행이 바뀌는데, 이는 * 연산자가 얕은 복사를 수행하여 사실상 다음과 같이 만들기 때문입니다:
index = [same_list, same_list, same_list]
올바른 방법
각 행마다 새로운 내부 리스트를 만들기 위해 리스트 컴프리헨션을 사용합니다:
index = [[0, 0] for _ in range(n)]
빠른 확인
index = [[0, 0] for _ in range(3)]
index[0][0] = 7
print(index)
출력
[[7, 0], [0, 0], [0, 0]]
이제 의도한 행만 수정됩니다.
*을 실제로 사용해도 괜찮은 경우
불변값과 함께 *을 사용하는 것은 전혀 문제되지 않습니다:
arr = [0] * 5 # 전혀 문제 없음
문제는 리스트와 같이 중첩된 가변 객체와 함께 사용할 때만 발생합니다.