본문 바로가기
C.W.K.
Stream
Lesson 04 of 07 · published

제너레이터 표현식과 리스트 컴프리헨션 고르기

~15 min · generator-expression, comprehension, lazy, memory

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

둘의 차이는 괄호보다 소비 방식이야

리스트 컴프리헨션은 결과를 모두 계산해 저장하고, 제너레이터 표현식은 다음 값이 필요할 때 계산해. 입력이 10억 개여도 제너레이터 객체 자체는 작지만 리스트는 모든 원소의 자리를 마련해야 해.

한 번 읽고 끝이면 흐르게 둬

sum, any, all, 첫 결과 찾기처럼 한 번만 소비하는 작업은 제너레이터와 잘 맞아. 답이 일찍 정해지면 뒤의 계산을 건너뛰어. 함수의 유일한 인자라면 괄호도 생략할 수 있어.

여러 번 읽거나 위치 접근이 필요하면 리스트

같은 결과를 반복해서 걷고, 길이와 인덱스를 쓰고, 정렬하거나 뒤에서 읽어야 한다면 처음부터 리스트로 만드는 편이 맞아. 필요한 시점에 list(generator)로 구체화할 수도 있지만 그 순간 메모리 비용을 치러.

원칙: 생산 방식이 아니라 소비 계약으로 선택해. 한 번 흐르면 제너레이터, 보관하고 다시 읽으면 리스트야.

Code

리스트와 제너레이터의 메모리 차이·python
import sys

lc = [x*x for x in range(1_000_000)]    # 백만 원소 list
gen = (x*x for x in range(1_000_000))    # generator 객체

print(sys.getsizeof(lc))        # ~8MB
print(sys.getsizeof(gen))       # ~200 바이트 — 작아

# 소비할 때 같은 답
print(sum(lc) == sum((x*x for x in range(1_000_000))))  # True
답이 정해지면 계산을 멈추는 제너레이터·python
def expensive(x):
    print("computing", x)
    return x * x

# list 컴프리헨션 — 모든 원소 *먼저* 계산
result_list = any(v > 10 for v in [expensive(x) for x in [1, 2, 3, 4, 5]])
# 'computing' 5 줄 모두 출력 *후* 체크

print("---")

# generator expression — 매치 찾으면 short-circuit
result_gen = any(expensive(x) > 10 for x in [1, 2, 3, 4, 5])
# 딱 필요한 만큼만 — 첫 hit 에서 멈춤
여러 번 소비해야 할 때는 리스트·python
# 이건 다시 작동하지 않아 — generator 는 첫 사용 후 소진
gen = (x*x for x in range(5))
print(list(gen))             # [0, 1, 4, 9, 16]
print(list(gen))             # []   <- 소진
print(sum(gen))              # 0    <- 여전히 소진

# 여러 번 써야 하면 list 컴프리헨션
lst = [x*x for x in range(5)]
print(list(lst))             # [0, 1, 4, 9, 16]
print(list(lst))             # [0, 1, 4, 9, 16]
print(sum(lst))              # 30
함수 인자에서 괄호를 생략하는 표기·python
nums = [1, 2, 3, 4, 5]

# 세 가지 다 작동, 세 번째가 가장 흔함
print(sum((x*x for x in nums)))     # 55
print(sum( (x*x for x in nums) ))   # 55
print(sum(x*x for x in nums))       # 55  <- 표준 idiom

# any/all/max/min 똑같이
print(any(x > 3 for x in nums))     # True
print(max(x*2 for x in nums))       # 10

External links

Exercise

100줄 파일이나 같은 크기의 여러 줄 문자열에서 각 줄의 공백을 없애고 빈 줄을 거른 뒤 첫 단어를 뽑아 네 글자보다 긴 것만 흘려보내는 제너레이터 파이프라인을 만들어. 마지막에만 set으로 구체화하고, 중간에 100줄짜리 리스트가 만들어지지 않았는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.