파이썬 lambda, filter, reduce

2021. 5. 18. 02:48γ†πŸ Python

μ‹œν€€μŠ€ν˜•: μ „μ²˜λ¦¬μ— reduce, map, filter μ‚¬μš© (3ν˜•μ œ)

읡λͺ…ν•¨μˆ˜ Lambda

  • ν•¨μˆ˜λŠ” ν”νžˆ μš°λ¦¬κ°€ μ•„λŠ” μΌλ°˜ν•¨μˆ˜μ™€ 읡λͺ…ν•¨μˆ˜λ‘œ λ‚˜λˆŒ 수 μžˆλ‹€.
  • 읡λͺ…ν•¨μˆ˜λŠ” μΌλ°˜ν•¨μˆ˜μ™€ 달리 호좜된 ν›„ μ¦‰μ‹œ μ†Œλ©Έλœλ‹€. (μΌλ°˜ν•¨μˆ˜λŠ” λ°˜ν™˜ 후에도 λ©”λͺ¨λ¦¬ μž‘μ•„λ¨ΉλŠ”λ‹€)
  • 읡λͺ…ν•¨μˆ˜λŠ” μΌλ°˜ν•¨μˆ˜λ³΄λ‹€ κ°„κ²°ν•˜κ²Œ μž‘μ„±ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.
  • μ΄λŸ¬ν•œ νŠΉμ„±μœΌλ‘œ lambda(읡λͺ…ν•¨μˆ˜)ν•¨μˆ˜λŠ” κ°„κ²°ν•˜κ³  μΌνšŒμ„±μœΌλ‘œ μ‚¬μš©ν•  ν•¨μˆ˜ μž‘μ„±μ— μ‚¬μš©λœλ‹€.
# μΌλ°˜ν•¨μˆ˜
def func_name(a, b):

    return a + b

# 읡λͺ…ν•¨μˆ˜
total = lambda a, b: a + b

# 읡λͺ…ν•¨μˆ˜λŠ” ν•¨μˆ˜λͺ… μ •ν•˜λŠλΌ 골 μ•„ν”Œ 일도 μ—†λ‹€. (말 κ·ΈλŒ€λ‘œ '읡λͺ…' ν•¨μˆ˜)

lambda ν•¨μˆ˜ μ˜ˆμ‹œ

  • 1~10κΉŒμ§€μ˜ μžμ—°μˆ˜λ₯Ό 각각 μ œκ³±ν•˜μ—¬ λ¦¬μŠ€νŠΈμ— μ €μž₯ν•΄λ³΄μž.
  • μΌλ°˜ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‚΄λΆ€μ—μ„œ forλ¬Έ λŒλ¦¬λŠ” λŒ€μ‹ , lambda 읡λͺ…ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ μ†μ‰½κ²Œ μ²˜λ¦¬ν•  수 μžˆλ‹€.
digits1 = [x * 10 for x in range(1, 11)]  # 10개의 μ›μ†Œ 가진 리슀트 생성

# ν•œλ²ˆ μ‚¬μš©ν•˜κ³  λ§ˆλŠ”, 일회용의, μ¦‰μ‹œ μ‚¬μš©ν•˜λŠ” : lambda
result = map(lambda i: i ** 2, digits1)
print(result)
# >>> <map object at 0x1098b9370> : ν˜• λ³€ν™˜ ν•„μš” (list casting)

μœ„μ˜ resultλ₯Ό 좜λ ₯ν•˜λ©΄ casting 되기 μ „μ˜ objectν˜•νƒœμ˜ 값이 좜λ ₯λœλ‹€. 즉 μš°λ¦¬κ°€ μ‰½κ²Œ 확인할 수 μžˆλŠ” 데이터 νƒ€μž…μœΌλ‘œ ν˜• λ³€ν™˜μ΄ ν•„μš”ν•˜λ‹€.

# μœ„μ˜ κ²°κ³Όμ—μ„œ list()λ₯Ό μ‚¬μš©ν•˜μ—¬ ν˜•λ³€ν™˜ ν•΄μ€€λ‹€.
result = list(map(lambda i: i ** 2, digits1))
print("Ex 2 >", result)
# >>> Ex 2 > [100, 400, 900, 1600, 2500, 3600, 4900, 6400, 8100, 10000]

labmda κ²°λ‘ 

  • μΌλ°˜ν•¨μˆ˜λŠ” μž¬μ‚¬μš©μ„± μœ„ν•΄ λ©”λͺ¨λ¦¬μ— μ €μž₯되기 λ•Œλ¬Έμ— garbage collector μ—μ„œ 필터링이 λ˜μ§€ μ•ŠλŠ”λ‹€. (λŒ€μΆ© λ©”λͺ¨λ¦¬ μž‘μ•„λ¨ΉλŠ”λ‹€λŠ” μ†Œλ¦¬)
  • λ°˜λŒ€λ‘œ lambda ν•¨μˆ˜λŠ” μ‚¬μš©λœ 직후, python garbage collector에 μ˜ν•΄ 곧 λ°”λ‘œ μ œκ±°λœλ‹€. (λ©”λͺ¨λ¦¬ νš¨μœ¨μ„± μ¦λŒ€)
  • κ·ΈλŸ¬λ―€λ‘œ μΌνšŒμ„±μœΌλ‘œ μ‚¬μš©ν•˜κ³  싢은 ν•¨μˆ˜λŠ”, λ©”λͺ¨λ¦¬λ₯Ό μž‘μ§€ μ•ŠλŠ” λžŒλ‹€(읡λͺ…ν•¨μˆ˜)λ₯Ό μ‚¬μš©ν•œλ‹€.
  • 즉, λžŒλ‹€μ˜ μž₯점은 κ°„κ²°μ„±κ³Ό λ©”λͺ¨λ¦¬ νš¨μœ¨μ„±μ— μžˆλ‹€.

filter()

  • filter() λ©”μ†Œλ“œλŠ” true인 쑰건만 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λ‘œ, lamada ν•¨μˆ˜μ—μ„œ true 쑰건에 λ§žλŠ” λ°μ΄ν„°λ§Œ filtering ν•˜μ—¬ μ €μž₯ν•  수 μžˆλ‹€.
  • νŠΉμ • 쑰건으둜 κ±ΈλŸ¬μ„œ κ±ΈλŸ¬μ§„ μš”μ†Œλ“€λ‘œ iterator객체λ₯Ό λ§Œλ“€μ–΄μ„œ 리턴해쀀닀. (좜처: μœ„ν‚€λ…μŠ€)

1~10κΉŒμ§€ μžμ—°μˆ˜ 쀑 2의 배수만 λ¦¬μŠ€νŠΈμ— μ €μž₯ν•œλ‹€κ³  ν–ˆμ„ λ•Œ, ν”νžˆ forλ¬Έ κ³Ό if문을 μ‚¬μš©ν•˜μ—¬ λ¦¬μŠ€νŠΈμ— μ €μž₯ν•˜λ € ν•œλ‹€.
반면 filter와 lambda ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄, for, if 쑰건문을 μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# λžŒλ‹€μ˜ 쑰건식이 λ“€μ–΄κ°€λ©΄ filter μΉœλ‹€ => 쑰건의 true μ›μ†Œλ§Œ result에 μ €μž₯λœλ‹€.
result = list(filter(lambda x: x % 2 == 0, digits))
print(result)
# >>> [2, 4, 6, 8, 10]

reduce()

  • reduce(집계 ν•¨μˆ˜, 순회 κ°€λŠ₯ν•œ 데이터[, μ΄ˆκΈ°κ°’])
  • reduce() ν•¨μˆ˜λŠ” sequence λ°μ΄ν„°μ—μ„œ μ›μ†Œλ₯Ό λˆ„μ ν•  λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€.
  • μ΄ˆκΈ°κ°’μ€ μƒλž΅λ  경우 0으둜 μ΄ˆκΈ°ν™” λœλ‹€.
  • λ¬Έμžν˜•μ— λŒ€ν•΄μ„œλ„ reduce λˆ„μ ν•©κ³„ κ°€λŠ₯
# Ex 4 : reduce
# sequence ν˜• λ°μ΄ν„°μ—μ„œ μ›μ†Œλ₯Ό λˆ„μ ν•  λ•Œ μ‚¬μš© κ°€λŠ₯
from functools import reduce
digits3 = [x for x in range(1, 6)]
# >>> [1, 2, 3, 4, 5]

reduce의 연산과정을 ν’€μ–΄μ“°λ©΄

result = reduce(lambda x, y: x + y, digits3)

>>> 0
0
>>> 0 + 1
1
>>> 1 + 2
3
>>> 3 + 3
6
>>> 6 + 4
10
>>> 10 + 5
15

print(result) # 1~5 λˆ„μ  ν•©
>>> 15

즉 1λΆ€ν„° 5κΉŒμ§€μ˜, digits3 리슀트의 λͺ¨λ“  값듀을 μ°¨λ‘€λ‘œ λˆ„μ ν•˜λŠ” 과정을 확인할 수 μžˆλ‹€.