Python 리스트 컴프리헨션과 메모리 절약: 더 빠르고 효율적인 코드 작성법
Python의 리스트 컴프리헨션(list comprehension)은 짧고 간결하게 리스트를 생성할 수 있는 문법입니다. 반복문과 조건문을 결합해 하나의 줄로 리스트를 생성하면서, 메모리를 절약할 수 있는 방법도 제공합니다. 이번 글에서는 리스트 컴프리헨션의 기본 개념과, 메모리 사용을 최소화하면서 효율적으로 코드를 작성할 수 있는 활용법을 설명합니다.
1. 리스트 컴프리헨션이란?
리스트 컴프리헨션은 하나의 표현식으로 리스트를 생성할 수 있는 Python의 특별한 문법입니다. 일반적인 for
반복문으로 리스트를 작성하는 방법보다 간결하고 읽기 쉽습니다.
기본 구조
리스트 컴프리헨션의 기본 구조는 다음과 같습니다:
[표현식 for 요소 in 반복 가능한 객체 if 조건]
위 구조에서, if 조건
은 옵션으로 사용할 수 있는 필터입니다. 이 조건에 맞는 요소만 리스트에 포함됩니다.
2. 기본 예제: 리스트 컴프리헨션을 활용한 간결한 리스트 생성
다음은 for
반복문을 사용한 코드와 동일한 작업을 리스트 컴프리헨션으로 간단하게 작성한 예제입니다.
# 기존 방식
numbers = []
for i in range(10):
if i % 2 == 0:
numbers.append(i)
print(numbers) # [0, 2, 4, 6, 8]
# 리스트 컴프리헨션 사용
numbers = [i for i in range(10) if i % 2 == 0]
print(numbers) # [0, 2, 4, 6, 8]
결과
[0, 2, 4, 6, 8]
설명
- 기존 방식에서는
for
반복문과if
조건을 사용해 짝수를 골라내 리스트에 추가해야 했습니다. - 리스트 컴프리헨션을 사용하면 하나의 줄로 같은 결과를 얻을 수 있습니다. 간결하고, 읽기 쉬운 코드가 됩니다.
3. 메모리 절약하기: 제너레이터 표현식 사용
리스트 컴프리헨션은 메모리를 많이 사용하는 큰 리스트를 만들 때 부담이 될 수 있습니다. 이때는 제너레이터 표현식(generator expression)을 사용하여 메모리를 절약할 수 있습니다. 제너레이터는 모든 값을 한꺼번에 생성하지 않고 필요할 때마다 값을 생성하여 메모리 사용을 최소화합니다.
# 리스트 컴프리헨션 - 메모리 많이 사용
squares_list = [i * i for i in range(1000000)]
# 제너레이터 표현식 - 메모리 절약
squares_gen = (i * i for i in range(1000000))
print(sum(squares_list)) # 리스트 전체를 메모리에 올리므로 메모리 많이 사용
print(sum(squares_gen)) # 필요할 때마다 값을 생성하여 메모리 절약
설명
[i * i for i in range(1000000)]
는 리스트 컴프리헨션으로 모든 제곱 값을 메모리에 저장합니다.(i * i for i in range(1000000))
는 제너레이터 표현식으로 값을 필요할 때마다 생성하므로 메모리 사용을 줄일 수 있습니다.- 큰 데이터나 무한 시퀀스를 처리할 때 제너레이터 표현식을 사용하면 메모리 부담 없이 작업을 수행할 수 있습니다.
4. 조건부 리스트 컴프리헨션으로 필터링 작업 단순화하기
리스트 컴프리헨션의 if
조건을 활용하면 필터링 작업을 간단하게 수행할 수 있습니다. 조건에 맞는 요소만 포함하도록 리스트를 생성해보겠습니다.
# 기존 방식
filtered_numbers = []
for i in range(20):
if i % 3 == 0:
filtered_numbers.append(i)
print(filtered_numbers) # [0, 3, 6, 9, 12, 15, 18]
# 리스트 컴프리헨션 사용
filtered_numbers = [i for i in range(20) if i % 3 == 0]
print(filtered_numbers) # [0, 3, 6, 9, 12, 15, 18]
결과
[0, 3, 6, 9, 12, 15, 18]
설명
if
조건을 사용하면 조건에 맞는 요소만 리스트에 추가할 수 있습니다.- 필터링 작업이 간단해지고, 코드를 읽는 사람도 조건이 무엇인지 쉽게 이해할 수 있어 가독성이 높아집니다.
5. 리스트 컴프리헨션으로 중첩 반복문 처리하기
중첩 반복문이 필요할 때도 리스트 컴프리헨션을 사용하면 코드를 훨씬 짧고 간결하게 만들 수 있습니다.
# 기존 방식
pairs = []
for i in range(3):
for j in range(3):
pairs.append((i, j))
print(pairs) # [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# 리스트 컴프리헨션 사용
pairs = [(i, j) for i in range(3) for j in range(3)]
print(pairs) # [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
결과
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
설명
- 리스트 컴프리헨션을 사용하면 중첩 반복문을 간결하게 표현할 수 있습니다.
(i, j) for i in range(3) for j in range(3)
는i
와j
의 모든 조합을 리스트로 만듭니다. 코드가 짧아지고, 반복문이 한 줄로 정리되어 가독성이 높아집니다.
6. 조건문을 이용해 값 변환과 필터링을 동시에 수행하기
리스트 컴프리헨션은 조건에 따라 값을 변환하면서 리스트를 만들 수 있어, 코드가 간단해지고 실행 속도가 빨라집니다.
# 짝수는 그대로, 홀수는 제곱하여 리스트에 추가
numbers = [i if i % 2 == 0 else i * i for i in range(10)]
print(numbers) # [0, 1, 2, 9, 4, 25, 6, 49, 8, 81]
결과
[0, 1, 2, 9, 4, 25, 6, 49, 8, 81]
설명
i if i % 2 == 0 else i * i
는 짝수는 그대로 추가하고, 홀수는 제곱하여 리스트에 추가합니다.- 리스트 컴프리헨션을 사용하면 조건에 맞는 값을 쉽게 변환할 수 있어 필터링과 값 변환 작업을 동시에 수행할 수 있습니다.
7. 다중 조건을 사용해 복잡한 필터링 수행하기
리스트 컴프리헨션에서 if
조건을 여러 개 사용할 수 있어 다중 조건 필터링을 간단히 처리할 수 있습니다.
# 3의 배수이면서 짝수인 수만 리스트에 포함
numbers = [i for i in range(30) if i % 3 == 0 if i % 2 == 0]
print(numbers) # [0, 6, 12, 18, 24]
결과
[0, 6, 12, 18, 24]
설명
if i % 3 == 0 if i % 2 == 0
은 3의 배수이면서 짝수인 조건을 만족하는 값을 필터링합니다.- 다중 조건을 사용할 수 있어, 복잡한 조건이 필요한 필터링 작업도 한 줄로 간단하게 작성할 수 있습니다.
요약: 리스트 컴프리헨션과 메모리 절약
Python의 리스트 컴프리헨션은 간결하게 리스트를 생성하면서도 복잡한 조건을 적용하거나 필터링 작업을 수행할 수 있어 코드 가독성이 높아집니다. 또한, 메모리를 효율적으로 사용하는 제너레이터 표현식을 통해 대용량 데이터를 다룰 때도 부담을 줄일 수 있습니다.
리스트 컴프리헨션의 장점은 다음과 같습니다:
- 간결한 코드 작성: 반복문과 조건문을 하나의 표현식으로 작성하여 코드가 짧아지고 가독성이 높아집니다.
- 메모리 절약: 제너레이터 표현식을 사용하여 큰 데이터를 메모리에 부담 없이 다룰 수 있습니다.
- 필터링과 변환의 동시 수행: 조건문을 통해 데이터를 필터링하거나 변환하는 작업을 한 줄로 작성할 수 있습니다.
리스트 컴프리헨션과 제너레이터 표현식을 활용해 더 효율적이고 빠른 Python 코드를 작성해보세요!
'개발 > Python 스터디' 카테고리의 다른 글
[Python] `zip`과 `zip_longest`로 두 리스트 병합하기: 짝 맞추기 대작전 (0) | 2024.11.11 |
---|---|
[Python] `enumerate`로 간편하게 인덱스 추적하기: 인덱스와 값 모두 쉽게 관리하기 (0) | 2024.11.10 |
[Python] `yield` 완벽 가이드: 효율적인 데이터 처리와 제너레이터 사용법 (0) | 2024.11.08 |
[Python] `*`와 `**`를 함께 사용하기: 위치 인자와 키워드 인자 활용법 (0) | 2024.11.07 |
[Python] `**` 문법으로 복잡한 코드를 간단하게: 딕셔너리 언패킹과 키워드 인자 사용법 (1) | 2024.11.06 |