레슨 7 / 9·20분
컴프리헨션과 제너레이터
리스트 컴프리헨션
컴프리헨션은 반복 가능한 객체로부터 새로운 컬렉션을 간결하게 생성하는 Pythonic한 문법입니다. for 루프보다 읽기 쉽고 빠릅니다.
python
# 리스트 컴프리헨션 기본
squares = [x ** 2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 조건 필터링
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 조건 + 변환
words = ["Hello", "WORLD", "Python"]
lower_long = [w.lower() for w in words if len(w) > 5]
print(lower_long) # ["python"]
# 중첩 컴프리헨션 (2D 리스트 평탄화)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]딕셔너리 / 세트 컴프리헨션
python
# 딕셔너리 컴프리헨션
names = ["Alice", "Bob", "Charlie"]
name_lengths = {name: len(name) for name in names}
print(name_lengths) # {"Alice": 5, "Bob": 3, "Charlie": 7}
# 키-값 뒤집기
original = {"a": 1, "b": 2, "c": 3}
flipped = {v: k for k, v in original.items()}
print(flipped) # {1: "a", 2: "b", 3: "c"}
# 세트 컴프리헨션
text = "hello world"
vowels = {ch for ch in text if ch in "aeiou"}
print(vowels) # {"e", "o"}제너레이터
제너레이터는 값을 한 번에 하나씩 생성하는 이터레이터입니다. yield 키워드를 사용하며, 메모리를 절약할 수 있습니다. 대용량 데이터 처리에 유용합니다.
python
# 제너레이터 함수
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 사용
for num in fibonacci(10):
print(num, end=" ") # 0 1 1 2 3 5 8 13 21 34
print()
# 제너레이터 표현식 (메모리 효율적)
sum_squares = sum(x ** 2 for x in range(1000000))
print(sum_squares)
# 리스트 vs 제너레이터 메모리 비교
import sys
list_size = sys.getsizeof([x for x in range(10000)])
gen_size = sys.getsizeof(x for x in range(10000))
print("리스트:", list_size, "bytes") # ~87624 bytes
print("제너레이터:", gen_size, "bytes") # ~200 bytes
# yield from - 제너레이터 위임
def chain(*iterables):
for it in iterables:
yield from it
result = list(chain([1, 2], [3, 4], [5]))
print(result) # [1, 2, 3, 4, 5]- •
[expr for x in iterable]-- 리스트 컴프리헨션 - •
{k: v for ...}-- 딕셔너리 컴프리헨션 - •
{expr for ...}-- 세트 컴프리헨션 - •
(expr for x in iterable)-- 제너레이터 표현식 - •
yield-- 제너레이터 함수에서 값을 하나씩 반환
💡
컴프리헨션이 3중 이상 중첩되면 가독성이 떨어집니다. 복잡한 로직은 일반 for 루프가 더 명확합니다.