들어가기 전
- 이 글은 이펙티브 파이썬을 공부하며 작성한 글입니다
- 코드 : https://github.com/chickenchickenlove/effective-python/tree/master/item28
요약
- 컴프리헨션 내부에는 식을 2개 까지만 사용해라. (루프문 2개 / 루프문1 + 조건문1..)
- 컴프리헨션 내부에 2개의 루프식이 있는 경우, 왼쪽부터 실행된다. (이중 For문이라고 생각하면 편함. )
Item 28. 컴프리헨션 내부에 제어 하위식을 2개까지만 사용해라.
컴프리헨션 내부에서는 조건문, 루프문 등을 사용할 수 있다. 컴프리헨션 자체는 긴 코드를 짧게 줄일 수 있는 이점이 있지만, 너무 과하게 쓰면 '짧지만 읽기 어려운 코드'가 된다. 컴프리헨션 내부에 식이 3개 들어가는 순간부터 '짧지만 읽기 어려운 코드'가 되기 때문에 식을 2개까지만 사용하도록 제한한다.
- 루프문만 2개
- 루프문 1개 + 조건문 1개
즉, 위 두 가지 경우만 가능하다고 보면 된다.
코드 1
# 1. 루프문 2개만 사용
# 2. 컴프리헨션 루프문 2개는 왼쪽 -> 오른쪽으로 순서대로 실행됨.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
# 컴프리헨션 루프문 2개
squared = [[x**2 for x in row] for row in matrix]
- 루프문만 2개를 사용하는 경우다.
- 컴프리헨션 내에서 이중 루프는 왼쪽 → 오른쪽 순서로 평가된다. 이중 포문을 사용하는 것을 상상해보면 될 듯.
# 3개짜린 쓰지마라.
my_list = [
[[1, 2, 3], [4, 5, 6]],
[[7, 8, 9], [10, 11, 12]]
]
# 루프문 3개가 들어갔음. 읽기 어렵고, 길다.
flat2 = [x for sublist1 in my_list for sublist2 in sublist1 for x in sublist2]
# 대신에 이런 식으로 쓰는게 더 낫다.
flat3 = []
for sublist1 in my_list:
for sublist2 in sublist1:
flat3.extend(sublist2)
- 반면 루프문이 3개 들어간 경우, 짧지만 읽기 어려운 코드가 된다. sublist1 → sublist2 → x까지 타고 가다가 개발자가 어디까지 코드를 읽었는지 Context를 잃어버릴 수도 있을 것이다.
- 이 때는 리스트 컴프리헨션 대신 이중 포문으로 풀어주는 것이 더 편리한 사용이 된다.
코드2
# 아래 리스트 컴프리헨션은 문법적으로 차이가 있지만, 둘다 동일한 결과를 나타냄.
# 루프문 1개 + 조건문 1개라서 읽기 쉬움.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [x for x in a if x > 4 if x % 2 == 0]
c = [x for x in a if x > 4 and x % 2 == 0]
- 컴프리헨션에 루프문 1개, 조건문 1개가 들어간 경우다. 식이 2개만 사용되었기 때문에 가독성이 좋음.
# 문제가 되는 경우.
# 루프문 2개, 조건문 2개. 코드는 짧지만 읽기가 매우 어렵다.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
filtered = [[x for x in row if x % 3 == 0]
for row in matrix if sum(row) >= 10]
# 이렇게 쓰는게 훨씬 낫다.
def choose_x3(l):
return [x for x in l if x % 3 == 0]
filtered_improved = [choose_x3(row) for row in matrix if sum(row) >= 10]
위 코드는 루프문 2개 + 조건문 2개가 들어간 리스트 컴프리헨션이다. 식의 내용은 다음과 같다.
- 합이 10이상인 Row에서 3의 배수인 요소만 뽑음
단순한 내용이지만, 코드만 봤을 때는 읽는 것이 쉽지 않다. 컴프리헨션 내부에는 식을 2개만 사용하는 것이 가독성이 좋기 때문에 루프문과 조건문을 함수로 나눴다. Row의 합이 10 이상인 녀석들에 대해서 Iteration 하는데, 여기서 3의 배수만 뽑는 함수(choose_X3)를 실행한다고 하니 좀 더 읽기 쉬운 코드가 된다.
'프로그래밍 언어 > 파이썬' 카테고리의 다른 글
Effective Python Item 16. 딕셔너리 Key에 대한 접근은 get을 사용하라. (0) | 2024.01.14 |
---|---|
Effective Python Item 10. 왈러스 연산자를 이용해 반복을 피하라 (0) | 2024.01.14 |
Effective Python Item 45. 어트리뷰트를 리팩토링하는 대신 @property를 사용하라 (0) | 2024.01.13 |
Effective Python Item 44. Setter, Getter 대신 Attribute를 사용하라. (0) | 2024.01.13 |
Effective Python Item 36. Iterator / Generator를 다룰 때는 itertools를 사용하라 (0) | 2024.01.13 |