lambda는 왜 쓰는가?

  • 익명함수이기 때문에 한번 쓰이고 다음줄로 넘어가면 힙(heap) 메모리 영역에서 증발
  • (참고) 가비지 컬렉터 (참조하는 객체가 없으면 지워버린다)
    • 파이썬에서는 모든것이 객체로 관리 되고 각 객체들은 레퍼런스 카운터를 갖게 됩니다. 이 카운터가 0 즉, 그 누구도 참조하지 않게 된다면 메모리를 환원 하게 됩니다.

 

람다함수는 적절한 곳에 잘 쓰인다면 코드가 간결해 보이지만, 그렇지 않고 남용하게 된다면 코드가 코드 가독성이 떨어질 수 있습니다. 

<목차>
1. lambda 함수 설명
2. lambda 함수와 map
3. lambda 함수와 filter

4. lambda 함수와 reduce

 

1. 파이썬 람다 함수 설명


원래 함수는 복잡한 명령들을 편하게 반복해서 사용할 수 있도록 모아두는 역할을 하는데, def 를 이용해서 다른곳에 함수를 만들고 그걸 또 호출해서 부르기까지의 수고가 필요하지 않은 그런 "일회성 함수"들을 위해서 만들어진게 람다 함수 입니다.

> 람다함수 선언 방법

lambda 인자: 표현식

lambda 라는 키워드를 입력하고 뒤에는 매개변수(인자)를 입력하고 콜론(:)을 넣은다음에 그 매개변수(인자)를 이용한 동작들을 적으면 됩니다.
예를 들면 인자로 들어온 값에 2를 곱해서 반환한다고 하면 lambda x : x * 2  이런식으로 됩니다.

> 람다함수와 일반함수 비교

위에서 설명했듯이 람다함수는 일반함수를 가볍게 만든 함수이기 때문에 
짝수를 판별하는 함수를 만든다고 했을때 일반함수는
def is_even(x):
  return x % 2 == 0
이런식으로 표현을 할 수 있습니다.

이걸 람다로 표현하게 되면
is_even = lambda x : x % 2 == 0
이런식으로 표현할수 있습니다.

물론 일반함수, 람다함수 둘다 사용법은 같습니다.

 


is_even(1) # False
is_even(2) # True

 

2. 파이썬 lambda 함수와 map


map함수는 리스트나 튜플에 어떤 특별한 처리를 할때 사용하는 함수입니다.

> map 함수의 모양과 사용법

map(함수, 리스트나 튜플)

첫번째 인자인 함수는 두번째 인자로 들어온 리스트나, 튜플에 특별한 가공 처리를 하는 함수이며, 사용자가 직접 함수를 정의해서 넣습니다.
두번째 인자인 리스트나 튜플은 바꾸고자 하는 데이터들을 집어 넣습니다.

예를들어 리스트의 모든값에 2씩 더해서 새로운 리스트를 만든다고 할때  map 함수는 아래와 같이 사용할 수 있습니다.
map 의 반환값을 리스트로 다시 변경할수 있는데요 이때는 list(map(~~~)) 이런식으로 list 로 형변환해주는 함수로 감싸주면 됩니다.

# 1. 일반 함수 버전
def plus_two(x):
    return x + 2

result1 = list(map(plus_two, [1, 2, 3, 4, 5]))
print(result1)

## 실행결과
[3, 4, 5, 6, 7]

# 2.  람다 함수 버전
result2 = list(map((lambda x: x + 2), [1, 2, 3, 4, 5]))
print(result2)

## 실행결과
[3, 4, 5, 6, 7]
# 1. 일반 함수 버전
def plus_two(x):
    return x + 2

result1 = list(map(plus_two, [1, 2, 3, 4, 5]))
print(result1)


# 2.  람다 함수 버전
result2 = list(map((lambda x: x + 2), [1, 2, 3, 4, 5]))
print(result2)

 

이런식으로 def를 통해서 함수를 map의 인자로 전달해줘도 되지만,
map을 통해서 "리스트를 가공하는게 이번 한번 뿐이다" 라는 상황이라던지 lambda를 사용해서 간단하게 작업이 가능한 경우라면
람다 함수 사용을 고려해보는 것도 좋을듯 합니다.

여기서 range를 또 결합하면 
result3 = list(map((lambda x : x + 2), range(2, 6))) 이런식으로도 쓸 수 있습니다.

result3 = list(map((lambda x : x + 2), range(2, 6)))
print(result3)

-- 실행결과
[4, 5, 6, 7]

이렇게 람다 함수는 map 함수와 같이 사용자 정의 함수를 받을때 유용하게 작성할 수 있습니다.

 

3. python 람다 함수와 filter


filter 함수는 map 함수와 비슷하게  첫번쨰 인자로 함수를 받고, 두번째 인자로 리스트나 튜플을 받습니다.

> filter 함수 모양과 설명

filter(함수, 리스트나 튜플)

첫번째 인자에는 두번째 인자로 들어온 리스트나 튜플을 하나하나씩 받아서 필터링할 함수를 넣습니다.
두번쨰 인자에는 리스트나 튜플을 집어 넣습니다.

예를들어 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 까지의 리스트가 있을때 짝수들만 filter 함수를 이용해서 리스트를 다시 만든다고 했을때, filter 함수와 람다를 이용할 수 있습니다.

# 1. 일반 함수 버전
def is_even(x):
    return x % 2 == 0


result1 = list(filter(is_even, range(10)))  # [0 ~ 9]
print(result1)

## 실행결과
[0, 2, 4, 6, 8]

# 2.  람다 함수 버전
result2 = list(filter((lambda x: x % 2 == 0), range(10)))  # [0 ~ 9]
print(result2)

## 실행결과
[0, 2, 4, 6, 8]

 

결과 화면을 보앗듯 filter 함수의 첫번째 인자가 True 인 경우의 값만 가지고와서 리스트를 만들었습니다.
 filter 함수와 람다 함수를 결합하여 깔끔하게 filter가 가능합니다.

일회성 함수를 위해서 "def 함수 ~~" 이런작업을 해주지 않아도 됩니다.

4. python 람다 함수와 reduce


python3 부터 내장함수에서 빠졌습니다.  사용하려면 functools 모듈에서 reduce 함수를 가져와야 합니다

 

filter 함수는 map 함수와 비슷하게  첫번쨰 인자로 함수를 받고, 두번째 인자로 리스트나 튜플을 받습니다.

reduce() 함수는 두 개의 필수 인자와 하나의 옵션 인자를 가지는데, function 을 사용해서 iterable을 하나의 값으로 줄입니다. initializer 초기값을 의미합니다.
reduce() 함수를 사용할 때 많은 분들이 실수하는 부분이 있는데 바로 초기값 세팅 유무에 따라 이상한 결과가 나올 수 있는 것입니다.

예를 들어, 유저의 나이 합계를 구하는 예제에서 초기값으로 0을 넘겨주지 않으면 TypeError가 발생합니다.


functools 모듈의 reduce 함수는 다음과 같습니다. 

def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value

 

Syntax

reduce(함수, 리스트나 튜플[, initializer])

 

reduce()

reduce()은 리스트의 아이템들을 누적해서 하나의 값으로 리턴해주는 함수입니다. Lambda와 함께 사용할 수 있습니다.

reduce()의 첫번째 인자로 Lambda를 전달하고, 두번째 인자에 리스트를 전달합니다.

# 일반함수를 사용한 경우
from functools import reduce

def sum(x, y): 
    return x+y 
    
print(reduce(sum, range(10)))

print(lambda x,y : x+y, range(10)))

## 수행결과
45

# lambda를 사용한 경우
from functools import reduce

print(reduce(lambda x,y : x+y, range(10)))

## 수행결과
45

위에서 reduce의 연산 과정을 살펴보면, 처음에는 0 + 1이 수행되고, 그 결과를 다음 연산에 사용합니다. 그래서 그 다음에는 1 + 2이 수행되고, 3 + 36 + 4... 순서로 진행되어 마지막 값이 리턴됩니다. 따라서 결과는 0에서 9까지 합한 숫자가 리턴됩니다.

 

 

 

다음의 예제처럼 초기값을 10으로 주면, reduce 함수 코드에서 봤던 value 의 값에 10이 저장된 상태로 시작하기 때문에 10에 0부터 9까지의 합인 45를 더한 값이 리턴됩니다.

from functools import reduce

print(reduce(lambda x, y: x+y, range(10), 10))

## 실행결과
55

 

reduce 함수로 5 factorial 을 계산해 봅시다. 

from functools import reduce

print(reduce(lambda x, y: x*y, range(1, 5)))

## 실행결과
24


reduce 함수로 factorial 함수를 만들 수도 있습니다.

from functools import reduce

def factorial(n):
    return(reduce(lambda x, y: x*y, range(1, n+1)))

print(factorial(6))

## 실행결과
720

 

참고로, 파이썬은 다양한 수학적 연산을 지원하는 math 모듈을 내장하고 있는데 이 모듈에서 팩토리얼 함수를 제공합니다.
from math import factorial

print(factorial(6))

## 실행결과
720

'Python' 카테고리의 다른 글

python - decorator  (0) 2022.01.05
파이썬 - list  (0) 2022.01.05
Python 코드를 실행하는 Visual Studio Code에서 code runner 메시지를 숨기는 방법  (0) 2022.01.04
파이썬 시작하기  (0) 2022.01.03
[Python] VSCode argument 설정  (0) 2021.12.31

+ Recent posts