Python

[Python] [[]] * N 의 주의점

bornsoon 2025. 3. 28. 19:57

빈 리스트가 N개 나열된 중첩리시트를 만들고 싶어서 다음과 같은 코드를 실행했더니 엄청난 오류가 생겼다.

# N은 임의의 정수
answer_lst = [[]] * N

answer_lst[0] = ['1']

# print(answer_lst)        # for문 돌기 전 리스트 상태 : [['1'], [], []]

for i in range(N):
    answer_lst[i].append('1')
    print(i, '번째')
    print('answer_lst[i]:', answer_lst[i])
    print('answer_lst:', answer_lst)
    
# 출력값    
# 0 번째
# answer_lst[i]: ['1', '1']
# answer_lst: [['1', '1'], [], []]
# 1 번째
# answer_lst[i]: ['1']
# answer_lst: [['1', '1'], ['1'], ['1']]
# 2 번째
# answer_lst[i]: ['1', '1']
# answer_lst: [['1', '1'], ['1', '1'], ['1', '1']]
# [['1', '1'], ['1', '1'], ['1', '1']]

 

 

문제는 리스트 복사와 얕은 복사(shallow copy)때문이다.

answer_lst는 [[], [], []]처럼 보이지만, 실제로는 같은 리스트 객체를 세 번 참조하고 있다.

즉, 내부 리스트 []는 하나만 생성되고 , 그 참조가 여러 번 반복된 것이다.

answer_lst = [[]] * N
print([id(lst) for lst in answer_lst])

위 코드를 실행하면 같은 id값이 세 번 출력된다.

즉, answer_lst[0]을 변경하면 answer_lst[1]과 answer_lst[2]도 함께 바뀌는 것.

 

하지만, 다음과 같이 리스트가 아니라 숫자 0을 반복하는 것은 괜찮다. 

answer_lst = [0] * 9
answer_lst[0] = 1  # 첫 번째 요소만 변경

print(answer_lst)  
# [1, 0, 0, 0, 0, 0, 0, 0, 0]  ✅

왜냐하면,

리스트 [ ] 는 mutable(가변 객체) 를 * 연산자로 복제하면 모두 같은 리스트를 참조하지만,

숫자 0과 같은 immutable(불변 객체) 는 서로 영향을 주지 않는다.

 

 

📌 결론

  • [0] * 9 같은 immutable(불변 객체)는 안전 → 각각 독립적인 정수 값
  • [[]] * 3 같은 mutable(가변 객체)는 문제 발생 → 동일한 리스트 객체를 참조
  • 리스트나 딕셔너리 같은 가변 객체를 여러 개 만들려면 for 문이나 리스트 컴프리헨션을 사용해야 함.

따라서 다음과 같이 만들어야한다.

answer_lst = [[] for _ in range(N)]
728x90