C
Python/중급/Lesson 09

리스트 컴프리헨션

30분·theory
이 챕터
1/8
Python

리스트 컴프리헨션

🎯 이 lesson 을 읽고 나면

이 lesson 을 다 읽고 나면 아래 3가지를 자신 있게 할 수 있습니다.

  • ✅ 리스트 슬라이싱 + 컴프리헨션
  • ✅ list vs tuple 선택 + 깊은 복사 (copy.deepcopy)
  • ✅ sort vs sorted (원본 변경 여부)

학습 목표를 체크리스트로 두고 다 답할 수 있게 되면 lesson 을 닫으세요.

list comprehension 6가지 — 코드 + 실행 결과

[표현식 for 변수 in 반복가능 if 조건] — 리스트를 만드는 한 줄 문법. Python 의 정체성.


1. 가장 단순한 형태

python
# 일반 for 문
제곱 = []
for x in range(1, 6):
    제곱.append(x * x)
print(제곱)              # [1, 4, 9, 16, 25]

# list comprehension — 한 줄
제곱 = [x * x for x in range(1, 6)]
print(제곱)              # [1, 4, 9, 16, 25]

같은 결과, 한 줄. 읽기 더 쉬워짐 (변수 → 변환 → 출처 순).


2. 조건 추가 — if

python
숫자들 = [1, 2, 3, 4, 5, 6, 7, 8]

짝수 = [x for x in 숫자들 if x % 2 == 0]
print(짝수)              # [2, 4, 6, 8]

큰_짝수의_제곱 = [x * x for x in 숫자들 if x % 2 == 0 and x > 4]
print(큰_짝수의_제곱)    # [36, 64]

if필터. 표현식을 거치기 전에 통과 여부 결정.


3. 변환 — 문자열·dict 응용

python
이름들 = ["홍길동", "이몽룡", "성춘향"]

대문자 = [n.upper() for n in 이름들]      # 한국어는 영향 X
길이 = [len(n) for n in 이름들]
인사 = [f"안녕 {n}" for n in 이름들]

print(인사)              # ['안녕 홍길동', '안녕 이몽룡', '안녕 성춘향']
print(길이)              # [3, 3, 3]

4. dict / set comprehension

python
이름들 = ["홍길동", "이몽룡", "성춘향"]

# dict comprehension — {key: value for ...}
길이맵 = {n: len(n) for n in 이름들}
print(길이맵)            # {'홍길동': 3, '이몽룡': 3, '성춘향': 3}

# set comprehension — {value for ...}
글자_set = {글자 for 이름 in 이름들 for 글자 in 이름}
print(글자_set)          # {'홍', '길', '동', '이', '몽', '룡', '성', '춘', '향'}

5. 중첩 (이중 for) — 신중히

python
# 구구단 — 2단·3단의 모든 조합
구구단 = [(i, j, i*j) for i in range(2, 4) for j in range(1, 5)]
print(구구단[:4])
# [(2, 1, 2), (2, 2, 4), (2, 3, 6), (2, 4, 8)]

⚠️ 3중 이상 중첩은 읽기 어려움 — 일반 for 문이 더 명확.


6. 안 좋은 예 — comprehension 남용

python
# ❌ 너무 복잡 — 6 줄 짜리 한 줄
결과 = [(i, j) for i in range(10) for j in range(10) if i + j > 10 and i != j]

# ✅ 일반 for 문이 더 명확
결과 = []
for i in range(10):
    for j in range(10):
        if i + j > 10 and i != j:
            결과.append((i, j))

규칙: 이중 for + 조건 2개 이상이면 일반 for.


한 줄 요약

패턴문법
변환만[f(x) for x in xs]
변환 + 필터[f(x) for x in xs if cond(x)]
dict{k: v for x in xs}
set{f(x) for x in xs}

핵심: 간단할 때만 사용. 3 줄 넘으면 일반 for.

💻 나쁜 예시 — 복잡한 중첩 컴프리헨션
# 읽기 어려운 중첩 컴프리헨션
result = [x*y for sublist in [[1,2],[3,4],[5,6]] for x in sublist for y in range(x) if y % 2 == 0]
# 무슨 의미인지 즉시 파악 불가

# 불필요한 컴프리헨션 — 단순 합계에는 sum() 사용
total = sum([x**2 for x in range(100)])  # list 생성 불필요
# 대신: sum(x**2 for x in range(100)) — 제너레이터 직접
💻 좋은 예시 — 컴프리헨션 4종 활용
# 리스트 컴프리헨션
squares = [x**2 for x in range(10)]
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

# 조건부 표현식 (삼항)
labels = ['짝수' if x % 2 == 0 else '홀수' for x in range(5)]
print(labels)  # ['짝수', '홀수', '짝수', '홀수', '짝수']

# 딕셔너리 컴프리헨션
users = [{'id': 1, 'name': '홍길동'}, {'id': 2, 'name': '김철수'}]
user_map = {u['id']: u['name'] for u in users}  # {1: '홍길동', 2: '김철수'}

# 딕셔너리 키/값 스왑
original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}  # {1: 'a', 2: 'b', 3: 'c'}

# 세트 컴프리헨션 — 중복 자동 제거
words = ['apple', 'banana', 'apple', 'cherry']
first_letters = {w[0] for w in words}  # {'a', 'b', 'c'}

# 제너레이터 표현식 — 메모리 효율
total = sum(x**2 for x in range(1_000_000))  # 리스트 생성 안 함

# 중첩 컴프리헨션 — 2단까지는 괜찮음
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 중첩 3단 이상은 for문으로
cube_coords = []
for x in range(3):
    for y in range(3):
        for z in range(3):
            cube_coords.append((x, y, z))  # 가독성 우선

🐍 실행해보기 — 리스트 컴프리헨션

위 개념을 실제로 코드로 실행해보세요. 값을 바꿔가며 어떻게 동작하는지 직접 확인하는 게 가장 빠른 학습.
✏️ Python 코드
📟 콘솔 출력
▶ 실행 버튼을 눌러보세요
🐍 Pyodide로 실제 Python 실행 — 첫 실행 시 로딩 3~5초 소요

🤖 AI 에게 이렇게 요청해보세요

이 lesson 의 개념을 알면 AI 에게 구체적으로 지시할 수 있습니다. 막연한 "고쳐줘" 가 아니라 어휘를 가진 요청 — 그게 토큰 절약의 출발점입니다.

  • "이 for + append 를 리스트 컴프리헨션으로 바꿔줘"
  • "이 코드의 깊은 복사 (copy.deepcopy) 필요성 점검해줘"

왜 이게 토큰을 줄이나

개념을 모를 땐 AI 답변을 받고도 "그게 뭐예요?" 를 다시 물어야 합니다. 그 "다시 물음" 이 토큰을 잡아먹습니다. 개념 한 번 익혀두면 대화가 한 번에 끝납니다.

먼저 읽으면 좋은 개념: set — 중복 없는 집합
다음 추천: 람다 함수
리스트 컴프리헨션 - Python