제너레이터 표현식(generator expression)은 파이썬에서 데이터 시퀀스를 메모리 효율적으로 생성하는 방법입니다. 리스트 컴프리헨션과 비슷하지만, 대괄호 [] 대신 소괄호 ()를 사용합니다.
(식 for 변수 in 범위)처럼 소괄호로 표현됩니다.
예를 들어 (x*2 for x in range(5))는 0, 2, 4, 6, 8을 차례로 만들어내는 제너레이터입니다. 하지만 모든 값을 한 번에 만들지는 않고, 요청받을 때마다 하나씩 생성합니다.
주요 특징:
1️⃣ 지연 평가(lazy evaluation): 모든 결과를 한 번에 메모리에 저장하지 않고, 필요할 때만만 값을 한 번에 하나씩 생성합니다.
2️⃣ 메모리 효율성: 리스트 컴프리헨션과 달리 전체 결과를 메모리에 저장하지 않습니다.
3️⃣ 일회성 반복: 한 번만 반복할 수 있습니다.
<예시>
# 리스트 컴프리헨션 - 모든 값을 메모리에 저장
list_comp = [x*x for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 제너레이터 표현식 - 필요할 때만 값을 생성
gen_exp = (x*x for x in range(10)) # <generator object <genexpr> at 0x...>
# 제너레이터 사용
for i in gen_exp:
print(i) # 0, 1, 4, 9, ... 순서대로 출력
두 제너레이터 표현식을 ==로 비교하면 내용물을 비교하는 게 아니라 '서로 같은 객체인지'를 비교합니다.
아래 코드를 보세요:
a = (x for x in [1, 2, 3])
b = (x for x in [1, 2, 3])
print(a == b) # False가 출력됩니다
두 제너레이터 표현식이 같은 값을 생성하더라도 다른 메모리 공간에 있는 다른 객체이므로 False가 됩니다.
문법적 차이
리스트 컴프리헨션: 대괄호 []를 사용합니다.
[x*2 for x in range(10)]
제너레이터 표현식: 소괄호 ()를 사용합니다.
(x*2 for x in range(10))
메모리 사용
리스트 컴프리헨션: 모든 결과를 즉시 계산하여 메모리에 리스트로 저장합니다.
제너레이터: 결과를 즉시 계산하지 않고, 필요할 때만 값을 생성합니다(지연 평가).
사용 방식
리스트 컴프리헨션: 여러 번 반복 접근이 가능합니다.
제너레이터: 한 번만 반복할 수 있으며, 소진되면 다시 사용할 수 없습니다.
성능
리스트 컴프리헨션: 큰 데이터셋에서는 메모리를 많이 사용합니다.
제너레이터: 메모리 효율적이어서 대용량 데이터 처리에 적합합니다.
예시
# 리스트 컴프리헨션
list_comp = [x*x for x in range(1000000)] # 즉시 100만 개의 값이 메모리에 저장됨
print(list_comp[500]) # 다시 접근 가능
print(list_comp[500]) # 여러 번 접근 가능
# 제너레이터 표현식
gen_exp = (x*x for x in range(1000000)) # 아직 계산되지 않음
next(gen_exp) # 첫 번째 값만 계산
sum(gen_exp) # 나머지 값들이 계산되고 소진됨
next(gen_exp) # StopIteration 오류 발생 - 이미 소진됨
리스트 컴프리헨션은 즉시 사용할 수 있는 결과가 필요할 때 유용하고, 제너레이터는 대용량 데이터를 메모리 효율적으로 처리할 때 유용합니다.