Python에서는 * 연산자를 사용하여 리스트나 문자열을 쉽게 복사하거나 확장할 수 있습니다.
이 연산은 매우 간편하지만, 작동 원리를 제대로 이해하지 못하면 의도치 않은 결과를 초래할 수 있습니다.
특히, 리스트와 같은 가변 객체(mutable object) 를 다룰 때는 주의가 필요합니다.
이번 글에서는 Python의 * 연산이 어떻게 작동하는지, 그리고 이를 사용할 때 발생할 수 있는 문제와 해결 방법을 알아보겠습니다.
1. * 연산의 기본 원리
Python의 * 연산자는 반복(repetition) 을 통해 객체를 복사하거나 확장하는 역할을 합니다.
대표적으로 문자열, 숫자, 리스트에서 활용됩니다.
(1) 문자열과 숫자의 경우
문자열과 숫자는 불변 객체(immutable object) 이므로, * 연산으로 복사해도 안전합니다.
s = "Python"
print(s * 3) # Output: PythonPythonPython
n = 42
print([n] * 3) # Output: [42, 42, 42]
(2) 리스트의 경우
리스트는 가변 객체(mutable object) 이므로, * 연산 시 주의가 필요합니다. 단순히 참조를 복사하기 때문에, 하나의 요소를 변경하면 모든 복사본이 영향을 받을 수 있습니다.
arr = [0] * 3
print(arr) # Output: [0, 0, 0]
arr[0] = 1
print(arr) # Output: [1, 0, 0] (안전)
위 예제는 안전해 보이지만, 2차원 이상의 리스트에서는 문제가 발생할 수 있습니다.
2. 가변 객체에서의 문제: 참조 공유
문제 상황: 2차원 리스트
arr = [[0] * 3] * 3
print(arr) # Output: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
arr[0][0] = 1
print(arr) # Output: [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
문제의 원인
[[0] * 3] * 3에서 내부 리스트 [[0] * 3]는 단일 리스트 객체를 참조하며, * 연산은 이 객체를 복사하는 대신 같은 객체를 여러 번 참조합니다.
따라서, 한 곳을 수정하면 모든 참조된 리스트가 동일하게 변경됩니다
3. 해결 방법: 독립적인 객체 생성
리스트 컴프리헨션을 사용
리스트 컴프리헨션을 사용하면 내부 리스트가 독립적인 객체로 생성됩니다.
arr = [[0] * 3 for _ in range(3)]
arr[0][0] = 1
print(arr) # Output: [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
4. 일반적인 사례와 해결 방법
상황 | 잘못된 코드 | 해결 코드 |
2차원 리스트 초기화 | arr = [[0] * N] * N | arr = [[0] * N for _ in range(N)] |
3차원 리스트 초기화 | arr = [[[0] * N] * N] * N | arr = [[[0] * N for _ in range(N)] for _ in range(N)] |
5. 정리: * 연산의 진실
- * 연산은 반복과 확장에 강력한 도구지만, 참조 복사로 인해 의도치 않은 부작용이 발생할 수 있습니다.
- 리스트와 같은 가변 객체를 다룰 때는 항상 참조의 공유 문제를 염두에 두어야 합니다.
- 안전한 다차원 리스트 초기화를 위해 리스트 컴프리헨션을 적극 활용하세요.
'Dev' 카테고리의 다른 글
[Python] pip를 사용한 외장 라이브러리 삭제 (1) | 2024.12.27 |
---|---|
[Java] Java의 Collection Framework에 대해 (0) | 2024.11.21 |
[Java] Double.MIN_VALUE는 음수가 아니다. (1) | 2024.11.20 |
[PowerShell] Windows에서 빈 폴더를 자동으로 삭제하는 PowerShell 스크립트 (1) | 2024.11.15 |
[Dev C++] Dev C++에서 for 내부 변수 선언 오류 해결 방법 (0) | 2024.11.09 |