평소와 똑같이 백준 문제를 풀고 있던 중 리스트를 만들다가 이상한 점을 발견했다.
리스트 안에 빈 리스트를 3개를 만들기 위해 다음과 같이 코드를 작성했다.
A = [[] for _ in range(3)]
B = [[]] * 3
A, B를 출력해 보면 [ [ ], [ ], [ ] ] 이런 형태의 2차원 리스트가 만들어지는 것을 볼 수 있다.
똑같아 보이지만 A, B는 차이가 있다.
이 차이는 값을 추가하거나 변경할 때 볼 수 있다.
다음과 같이 각 리스트의 0번 인덱스, 즉 0번 리스트에 1을 추가할 것이다.
A[0].append(1)
B[0].append(1)
위 코드로 우리가 의도하는 결과는 [ [1], [ ], [ ] ]이다.
하지만 실제로 A와 B를 출력해 보면 두 결과는 다른 것을 볼 수 있다.
나는 분명히 0번 인덱스에만 값을 넣었는데 왜 B의 전체 요소에 값이 추가된 거야?!
이번에는 값을 변경해 보자.
A[0][0] = 0
B[0][0] = 0
아니 이런. 값을 변경할 때도 B는 한꺼번에 바뀌어버리잖아?
그 이유는 다음과 같다.
B와 같이 *를 이용해 2차원 리스트를 생성할 경우 얕은 복사가 일어난다.
이 말은 즉, [[0] * 4] * 3으로 선언한 리스트는 [0] * 4 형태의 리스트 객체 1개를 모든 리스트가 바라보는 것이다.
이와 같은 이유로 B[0]에서 값을 추가하거나 변경하면 B[1]과 B[2]도 같은 객체를 바라보고 있기 때문에 모든 리스트에 결과가 반영된 것이다.
따라서, *보다는 for문을 사용해 만드는 것이 조금 더 안전하고 의도하는 대로 작동할 수 있으니 이 점에 주의해야 한다.
반응형