~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 써. 가독성이 이김.