C.W.K.
Stream
Lesson 06 of 07 · published

반복 헬퍼 — map / filter / 그리고 거의 안 쓸 이유

~15 min · map, filter, functional, comprehension

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

옛 코드에서 보게 될 functional 페어

map(fn, iterable)fn 을 각 원소에 적용. filter(pred, iterable)pred(x) 가 truthy 인 원소만 유지. Python 에 영원히 있었고, 대부분 언어에 있어. 근데 *더 이상 가장 Pythonic 한 방법은 아냐*. 컴프리헨션이 거의 항상 더 잘 읽혀.

왜 컴프리헨션이 보통 이기나

[x*2 for x in nums]list(map(lambda x: x*2, nums)) 보다 짧고 명확. [x for x in nums if x > 0]list(filter(lambda x: x > 0, nums)) 보다 좋아. 컴프리헨션은 표현식을 앞에 두고 술어를 뒤에 둬서, 결과가 먼저 읽혀. 그 가독성 편향이 컴프리헨션이 이긴 이유의 대부분.

map / filter 가 여전히 값어치 하는 경우

두 가지 — 매핑하는 함수가 *이미 이름 있을 때* (메서드 같은) 면 map(str.upper, words)[w.upper() for w in words] 보다 깔끔할 수 있어. 그리고 lazy iterator 원할 때 (list 안 만들어짐). Python 3 에서 map / filter 는 iterator 반환 — generator expression 처럼 lazy.

any / all — 저평가된 reducer

idiomatic 한 반복 헬퍼 두 개 — any(iterable) 은 어느 원소든 truthy 면 True. all(iterable) 은 모두 truthy 면 True. 둘 다 short-circuit. generator expression 과 결합하면 아름답게 읽혀 — if any(x < 0 for x in nums).

Pythonic Way: map / filter 손에 닿을 때 — 컴프리헨션이 더 깔끔하지 않은지 자문. 답이 yes 일 확률 90% 이상. 나머지는 진짜 케이스, 근데 예외야.

Code

map vs 컴프리헨션·python
nums = [1, 2, 3, 4, 5]

# functional 스타일
result = list(map(lambda x: x * 2, nums))
print(result)              # [2, 4, 6, 8, 10]

# 컴프리헨션 — 보통 더 명확
result = [x * 2 for x in nums]
print(result)              # [2, 4, 6, 8, 10]

# map 이 더 깔끔한 경우 — 함수가 이미 이름 있을 때
words = ["alpha", "beta", "gamma"]
upper = list(map(str.upper, words))      # 좀 더 좋아 보임
upper = [w.upper() for w in words]       # 이것도 OK
filter vs if 있는 컴프리헨션·python
nums = [-2, -1, 0, 1, 2]

# functional
positives = list(filter(lambda x: x > 0, nums))
print(positives)           # [1, 2]

# 컴프리헨션
positives = [x for x in nums if x > 0]
print(positives)           # [1, 2]

# 결합 — 컴프리헨션이 한 줄로
result = [x * 10 for x in nums if x > 0]
print(result)              # [10, 20]
any / all — 영어처럼 읽히는 reducer·python
nums = [1, 2, 3, 4, 5]

# 음수 있나?
print(any(x < 0 for x in nums))      # False

# 모두 양수?
print(all(x > 0 for x in nums))      # True

# 둘 다 short-circuit — 결정 나는 첫 원소에서 멈춤
def expensive(x):
    print("checking", x)
    return x > 100

any(expensive(x) for x in [50, 150, 200])
# checking 50
# checking 150  <- 여기서 True 반환, 200 안 봄
Python 3 에서 map 은 lazy iterator·python
result = map(str.upper, ["a", "b", "c"])
print(result)              # <map object at 0x...>
print(list(result))        # ['A', 'B', 'C']

# 소비된 후엔 빈 iterator
print(list(result))        # []

External links

Exercise

nums = [-3, -1, 0, 4, 7, 12]. (a) map / filter 만 (컴프리헨션 X, for 문 X) 양수의 제곱 list. (b) (a) 를 컴프리헨션 한 줄로 다시. (c) any 로 10 초과 있는지, all 로 모두 -5 초과인지 체크. 4 결과 다 출력.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.