|

파이썬 list comprehension은 언제 읽기 어려워질까: 짧은 코드와 가독성의 균형

파이썬 list comprehension 가독성 균형 대표 이미지
list comprehension은 짧게 쓰는 기술이 아니라, 한눈에 읽히는 변환을 표현하는 도구입니다.

파이썬 list comprehension은 코드를 짧고 깔끔하게 만들 수 있는 문법입니다. 하지만 모든 반복문을 한 줄로 줄이면 오히려 읽는 사람이 조건과 변환을 다시 해석해야 합니다.

핵심은 짧은 코드가 아니라 한눈에 읽히는 코드가 좋은 코드라는 점입니다. 이 글은 Python 공식 문서와 PEP 8의 가독성 원칙을 기준으로 list comprehension을 쓸 때와 for문으로 풀 때를 나눠 봅니다.

파이썬 list comprehension 사용 기준 요약 카드
짧은 코드보다 읽는 사람이 바로 이해하는 코드가 우선입니다.

파이썬 list comprehension이 잘 맞는 경우

list comprehension은 기존 iterable에서 새 리스트를 만들 때 가장 자연스럽습니다. 특히 한 가지 값을 한 가지 방식으로 바꾸고, 조건도 한눈에 읽히는 경우라면 for문보다 짧고 명확합니다.

names = ["kim", "lee", "park"]
upper_names = [name.upper() for name in names]

이 코드는 읽는 순서가 단순합니다. `names`를 돌면서 `name.upper()` 결과를 새 리스트로 만든다는 뜻이 바로 보입니다.

조건이 하나일 때는 아직 읽기 쉽다

필터링 조건이 하나 정도 붙는 것도 괜찮습니다. 조건이 변환의 부가 설명처럼 읽히기 때문입니다.

scores = [95, 72, 88, 61, 100]
passed = [score for score in scores if score >= 80]

여기서는 80점 이상만 고른다는 기준이 명확합니다. 변수 이름도 `passed`라서 결과의 의미가 코드 밖 설명 없이 드러납니다.

읽기 어려워지는 첫 번째 신호: 조건이 여러 겹이다

조건이 길어지고 `and`, `or`, 삼항 표현식까지 섞이면 한 줄의 장점이 줄어듭니다. 읽는 사람은 반복 대상, 조건, 변환을 한꺼번에 해석해야 합니다.

labels = [
    user.name.strip().title()
    for user in users
    if user.is_active and user.name and not user.is_blocked
]

이 정도는 팀에 따라 허용될 수 있습니다. 하지만 조건이 더 늘어나거나 예외 처리가 들어가면 for문으로 풀어 쓰는 편이 낫습니다.

labels = []
for user in users:
    if not user.is_active:
        continue
    if user.is_blocked or not user.name:
        continue
    labels.append(user.name.strip().title())

for문은 길지만 판단 단계가 나뉩니다. 나중에 로그를 넣거나 중간 조건을 바꾸기도 쉽습니다.

중첩 반복은 조심해서 써야 한다

list comprehension은 여러 for 절을 붙일 수 있습니다. 하지만 중첩 반복은 읽는 방향이 헷갈리기 쉽습니다.

pairs = [(x, y) for x in xs for y in ys if x != y]

짧은 조합 생성이라면 괜찮습니다. 하지만 실제 업무 코드에서 도메인 조건이 붙으면 ‘무엇을 먼저 돌고 무엇을 걸러내는지’가 흐려질 수 있습니다.

부작용이 있으면 list comprehension을 피한다

list comprehension은 새 리스트를 만드는 표현식입니다. 파일 저장, DB 업데이트, 로그 출력처럼 부작용이 목적이라면 for문이 더 솔직합니다.

# 피하는 편이 좋다
[send_email(user) for user in users]

# 의도가 더 분명하다
for user in users:
    send_email(user)

list comprehension은 결과 리스트가 필요할 때 쓰는 도구입니다. 결과를 버릴 거라면 반복문을 쓰는 편이 코드 의도가 더 정확합니다.

실무 체크리스트

  1. 한 줄을 읽고 결과의 의미가 바로 보이면 list comprehension을 쓴다
  2. 조건이 두세 단계로 나뉘면 for문으로 풀어 쓴다
  3. 중간값을 디버깅해야 하면 변수와 반복문을 사용한다
  4. 부작용이 목적이면 list comprehension을 쓰지 않는다
  5. 팀원이 다시 읽을 코드를 기준으로 판단한다

정리

list comprehension를 이해할 때는 문법을 짧게 쓰는 것보다, 코드가 표현해야 하는 의도를 먼저 보는 편이 좋습니다. 오늘 글의 기준은 ‘읽는 사람이 실수를 줄일 수 있는가’입니다.

함께 보면 좋은 내부 글은 파이썬 yield return 차이: generator는 왜 한 번에 다 만들지 않을까, 파이썬 예외 처리는 어디까지 잡아야 할까: bare except가 위험한 이유, 파이썬 dataclass는 왜 쓸까: class를 짧게 쓰는 것보다 중요한 이유입니다. 외부 기준은 Python Docs – Data Structures: List Comprehensions, Python Docs – Displays for lists, sets and dictionaries, PEP 8 – A Foolish Consistency is the Hobgoblin of Little Minds를 확인했습니다.

함께보면 좋은 글