C.W.K.
Stream
Lesson 06 of 07 · published

Comprehension — list / dict / set / generator

~25 min · comprehension, list-comp, dict-comp, generator-expression

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

가장 Pythonic 한 단일 문법 기능

경험 많은 Python 개발자 보면서 "초보랑 가장 다른 한 가지가 뭐냐" 물으면 — 컴프리헨션. for 문 돌려서 컬렉션 쌓는 *그 패턴 전체* — 한 줄짜리 읽기 쉬운 식으로 바뀌어. 한 번 익히면 더 짧고, 더 명백하게 옳은 loop 를 적게 쓰게 돼.

네 가지 맛

대괄호 — list 컴프리헨션. 콜론 있는 중괄호 — dict 컴프리헨션. 콜론 없는 중괄호 — set 컴프리헨션. 괄호 — generator expression. 같은 문법인데 lazy 하게 값 생성, 컬렉션 안 만들어. 그래서 sum(x*x for x in nums) 가 효율적 — 중간 list 가 안 만들어져.

문법 — 왜 filter 가 끝에 오나

왼쪽에서 오른쪽으로 읽는데 트위스트가 있어 — 원하는 *값 표현식이 먼저*, 그 다음 for, 그 다음 옵션인 if 필터. [x*2 for x in nums if x > 0]. 초보들이 자꾸 if 를 앞에 두려고 해 — 영어 어순으로 그게 자연스럽거든. Python 순서는 *값 만드는 식이 가장 도드라지게* 되도록 일부러 그렇게.

주의: 조건부 식 vs 필터 — 다른 거야. [x if x > 0 else 0 for x in nums] 는 항상 한 원소 만들어 (if/else 가 뭘 만들지 결정). [x for x in nums if x > 0] 는 원소 *떨궈*. 헷갈리지 마.

컴프리헨션을 *그만* 써야 할 때

for 절이 두 개 넘어가거나 깊이 중첩된 필터가 들어가면 컴프리헨션이 안 읽혀. 컴프리헨션 안에 컴프리헨션 박고 한 줄에 3 중첩 loop 쓰는 자신을 발견하면 — 그게 신호. 평범한 for 문 써. Pythonic = "한 줄에 다 쑤셔넣기" 가 아니야. Pythonic = "복잡도에 맞는 문법".

generator expression — 숨은 효율성 기능

generator expression 은 list 컴프리헨션처럼 보이는데 [...] 대신 (...). 차이점 — 순회하기 전엔 아무 것도 계산 안 해. sum(x*x for x in big_list) 는 중간 list 안 만들고, 한 번에 한 제곱만 계산하고 더하고 버려. iterable 을 소비하는 함수 (sum, any, all, max, min) 에는 list 컴프리헨션 대신 generator expression 넘겨. 보통 괄호도 생략 가능 — sum(x*x for x in nums)sum((x*x for x in nums)) 와 같아.

Code

list 컴프리헨션 — for-append 킬러·python
nums = [1, 2, 3, 4, 5]

# 장황한 방법
doubled = []
for n in nums:
    doubled.append(n * 2)
print(doubled)            # [2, 4, 6, 8, 10]

# 컴프리헨션
doubled = [n * 2 for n in nums]
print(doubled)            # [2, 4, 6, 8, 10]

# 필터 추가
evens_doubled = [n * 2 for n in nums if n % 2 == 0]
print(evens_doubled)      # [4, 8]
dict / set 컴프리헨션·python
words = ["alpha", "beta", "gamma"]

# dict — 콜론 = dict
lengths = {w: len(w) for w in words}
print(lengths)            # {'alpha': 5, 'beta': 4, 'gamma': 5}

# set — 콜론 X = set
length_set = {len(w) for w in words}
print(length_set)         # {4, 5}

# dict 뒤집기 (값이 hashable 일 때)
original = {"a": 1, "b": 2, "c": 3}
flipped = {v: k for k, v in original.items()}
print(flipped)            # {1: 'a', 2: 'b', 3: 'c'}
generator expression — 숨은 효율성·python
nums = range(1_000_000)

# list 컴프리헨션 — 백만 개 list 만들고 합산. ~30MB 사용.
total_list = sum([x * x for x in nums])

# generator expression — 한 번에 한 제곱만, 메모리 거의 안 씀
total_gen = sum(x * x for x in nums)

print(total_list == total_gen)              # True — 같은 답

# 괄호가 이미 있으면 안쪽 괄호 생략 가능
any(x > 100 for x in nums)
max(x * 2 for x in nums)
조건부 식 vs 필터 — 다른 거야·python
nums = [-2, -1, 0, 1, 2]

# 필터 — 원소 떨어뜨림
filtered = [x for x in nums if x > 0]
print(filtered)           # [1, 2]

# 조건부 — 모든 원소 살리고 변형
transformed = [x if x > 0 else 0 for x in nums]
print(transformed)        # [0, 0, 0, 1, 2]

# 둘 다 — 필터 + 변형
result = [x * 10 for x in nums if x > 0]
print(result)             # [10, 20]
중첩 컴프리헨션 — 조심해서 읽고, 일찍 리팩터·python
# 3x3 그리드
grid = [[i*3 + j for j in range(3)] for i in range(3)]
print(grid)               # [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

# 평탄화 — 순서 주의 — 바깥 for 가 먼저, 안쪽 for 가 두 번째
flat = [n for row in grid for n in row]
print(flat)               # [0, 1, 2, 3, 4, 5, 6, 7, 8]

# for 절 두 개 넘으면 그냥 loop 써. 가독성이 이김.

External links

Exercise

prices = [("AAPL", 180), ("MSFT", 420), ("GOOG", 145), ("NVDA", 950), ("TSLA", 215)]. 컴프리헨션만 써서 (for 문 X, .append X, map/filter X) — (a) 티커만 list, (b) {ticker: price} dict, (c) 가격 200 초과 티커 list, (d) 평균 가격 한 숫자 (sum(...) + generator expression). 넷 다 출력.

Progress

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

댓글 0

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

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