-
TIL. 28 람다 표현식(lambda) 사용하기TIL 2020. 11. 5. 18:23728x90
## lambda 표현식
## 람다 표현식은 식 형태로 되어 있어 람다 표현식이라 부르며,
## 함수를 간편하게 작성할 수 있어, "다른 함수의 인수"로 넣을때 자주 사용한다.
## 반화 값으로 매개변수 x + 10 형태의 함수를 람다 표현식으로 함수를 해보자
1. def
def ppp(x): return x+10 print(ppp(1)) :: 11
2. 람다 표현식
# 람다 표현식은 다음과 같이 lambda에 매개변수를 지정하고 :(콜론) 뒤에 반환값으로 사용할 식을 지정한다.
# lambda 매개변수들: 식
lambda x : x+10
# 람다 표현식을 위와 같이 작성하면 함수 객체가 생성되는데, 이 상태만으로는 함수를 호출 할 수 없다.
# 람다 표현식은 "이름없는"함수를 만들기 때문이다, 이때문에 람다 표현식을 익명 함수(anonymous function) 라고도 부른다.
## 람다로 만든 함수를 호출하기 위해선 임의의 변수에 할당하여 호출하면 된다.
a = lambda x : x+10 print(a(10)) :: 20
## 람다 표현식을 살펴보면 lambda x: x + 10은 매개변수 x 하나를 받고, x에 10을 더해서 반환한다는 뜻이다.
# 즉, 매개변수, 연산자, 값 등을 조합한 식으로 반환값을 만드는 방식이다
# 다음그림과 같이 def로 만든 함수와 비교해보자.
## 람다 표현식 자체로 호출하기
## 임의의 변수를 할당하지않고 ()로 묶어 람다 표현식 자체만으로도 함수를 호출 할 수 있는 방법이있다.
## (lambda 매개변수들: 식)(인수들) IDLE에서 좀 더 쉽게 확인가능
(lambda x : x+10)(25) # (lambda 매개변수들: 식)(인수들) print((lambda x : x+10)(25)) :: 35
## 람다 표현식안에서는 변수를 만들 수 없다.
(lambda x: y=10; x + y) # error
## 이처럼 y라는 변수를 람다 표현식에 만들 수 없다
## 따라서 반환값 부분은 변수 없이 식 1줄로 작성되어야 하며, 추가 변수가 필요할 경우 def 이용해야한다.
## 람다 표현식은 바깥에 있는 함수를 사용할 수 있다.
y = 20 (lambda x: x+y)(1) 출력시 :: 21
## 위와 같이 매개변수 x 와 바깥의 변수 y 를 이용해 값을 반환 할 수 있다.
## 람다 표현식을 사용하는 이유
## 람다 표현식은 "함수의 인수 부분에서 함수를 간단하게 만들기 위해 사용한다" 대표적으로 map이다.
def plus_ten(x): return x + 10 b = list(map(plus_ten, [1, 2, 3])) ## map 객체로 저장되는 값을 사람이 보기 위해 list로 변환시켜주는 과정 print(b) :: [11, 12, 13]
## map은 여러 개의 데이터를 한 번에 다른 형태로 변환하기 위해서 사용한다.
# 따라서, 여러 개의 데이터를 담고 있는 list나 tuple을 대상으로 주로 사용하는 함수이다.
### 지금까지 map을 사용할 때 map(str, [1, 2, 3])와 같이 자료형 int, float, str 등을 넣었다
### 사실 plus_ten처럼 함수를 직접 만들어서 넣어도 된다.
c = list(map(lambda x : x+10 ,[1, 2, 3])) # 위 식의 b와 비교해보면 plus_ten 이라는 함수 자리를 람다 표현식으로 대체한 것 print(c) :: [11, 12, 13]
## 위 식의 b와 비교해보면 plus_ten 이라는 함수 자리를 람다 표현식으로 대체한 것이며
## 대체할 경우 def 과정이 사라진 코드 단축효과를 볼 수 있다.
## 이처럼 "함수를 다른 함수의 인수로 넣을때" 편리하다
## 람다 표현식으로 매개변수가 없는 함수 만들기
f = (lambda: 1)() print(f) :: 1 x = 10 g = (lambda : x)() print(g) :: 10
## 람다 표현식으로 매개변수가 없는 함수를 만들 때는 lambda 뒤에 아무것도 지정하지 않고 :(콜론)을 붙혀준다.
## 단, 콜론 뒤에는 반드시 반환할 값이 있어야 한다. 왜냐하면 표현식(expression)은 반드시 값으로 평가되어야 하기 때문이다.
## 람다 표현식에서 map, filter, reduce 사용하기
## 람다 표현식에서 조건문 사용하기
# lambda 매개변수들: 식1 if 조건식 else 식2
## map을 이용해 a라는 리스트에서 3의 배수를 문자열로 출력
<IDLE> # not vscode a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] list(map(lambda x : str(x) if x % 3 == 0 else x,a)) :: [1, 2, '3', 4, 5, '6', 7, 8, '9', 10]
# map은 리스트의 요소를 각각 처리하므로 lambda 의 반환값도 요소여야 한다.
## 식 1 == str(x) , 조건식 == x % 3 == , 식2 == x
## 람다 표현식에서 조건문 사용시 주의할 점
## 1. if else 조건문 사용시 :(콜론)을 붙히지 않음 (일반적 조건문 문법과 다름)
## 2. 식1 if 조건식 else 식2 // 조건문이 참이면 식1, 거짓일때는 식2를 사용한다.
## 3. if를 사용했다면 반드시 else도 사용해줘야한다. (if만 사용시 error)
## 4. elif 를 사용 할 수 없다
## 람다 표현식에 조건문 여러개 사용하기
# lambda 매개변수들: 식1 if 조건식1 else 식2 if 조건식2 else 식3
# 리스트에서 1은 문자열로 변환하고, 2는 실수로 변환, 3 이상은 10을 더하는 식은 다음과 같이 작성
<IDLE> list(map(lambda x : str(x) if x== 1 else float(x) if x==2 else x+10,a)) :: ['1', 2.0, 13, 14, 15, 16, 17, 18, 19, 20]
## lambda 매개변수들: 식1 if 조건식1 else // 식2 if 조건식2 else 식3 ==>
//를 기준으로 왼쪽 조건식 1개, 오른쪽 조건식 1개로 이해하면 편하다
## 위 식을 def로 바꿔 작성해보자
def f(x): if x == 1: return str(x) elif x == 2: return float(x) else: return x+10 a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] b = list(map(f,a)) print(b) :: ['1', 2.0, 13, 14, 15, 16, 17, 18, 19, 20]
## 조건이 복잡하여 이해하거나 알아보기 힘들경우 억지로 람다 표현식을 사용하지 말고, def로 사용하는것을 권장한다.
## 복잡하고 어려운 코드는 작성 후 시간이 지나면 알아보기 어려운 경우가 많으니,
코드는 길이가 조금 길어지더라도 알아보기 쉬워야 한다.(중요)
## mpa에 객채 여러개 넣기
<IDLE> a = [1, 2, 3, 4, 5] b = [2, 4, 6, 8, 10] list(map(lambda x, y: x * y, a, b)) :: [2, 8, 18, 32, 50]
## map은 리스트 등의 반복 가능한 객체를 여러개 넣을 수 있다.
## 위 코드는 두 리스트의 요소를 서로 곱해 새로운 리스트를 만드는 방법이다.
## 리스트 2개를 처리해야하는 경우 lambda x, y : x*y 처럼 매개변수를 2개 지정해주면 된다.
## 그다음 리스트 2개를 ,(콤마)로 구분해 넣어주면 된다.
## 즉, 람다 표현식의 매개변수 개수에 맞춰 반복 가능한 객체를 콤마로 구분하여 넣어주면 된다.
## 여기서 반복 가능한 객체는 a, b 이며, a, b 의 요소의 개수가 다를 경우 요소의 개수가 더 작은 객체를 기준으로 출력해준다
## ex : a = [1, 2] ==> 해당 식의 반환 값은 [2, 8] 까지만 반환
## ex : a = [1, 2, 3, 4, 5, 6, 7, 8] ==> 해당 식의 반환 값은 [2, 4, 6, 8, 10] 까지만 반환 (b의 요소 개수 5개)
## filter 사용하기
# filter는 반복 가능한 객체에서 특정 조건에 맞는 요소만 가져오는데,
# filter에 지정한 함수의 반환값이 True일 때만 해당 요소를 가져온다.
# filter(함수, 반복가능한객체)
## def를 이용한 리스트에서 5보다 크면서 10보다 작은 숫자를 가져오기.
a = [8, 3, 2, 10, 15, 7, 1, 9, 0, 11] def aaa(x): return x > 5 and x <10 print(list(filter(aaa, a))) :: [8, 7, 9]
## 람다 표현식을 이용한 리스트에서 5보다 크면서 10보다 작은 숫자를 가져오기.
a = [8, 3, 2, 10, 15, 7, 1, 9, 0, 11] b = list(filter(lambda x : x > 5 and x < 10, a)) print(b) :: [8, 7, 9]
## 즉 filter 는 x > 5 and x <10 조건 중 참인 것만을 가져오고, 거짓은 버림
## reduce 사용하기
# reduce는 반복 가능한 객체의 각 요소를 지정된 함수로 처리한 뒤 이전 결과와 누적해서 반환하는 함수
# (reduce는 파이썬 3부터 내장 함수가 아닙니다. 따라서 functools 모듈에서 reduce 함수를 가져와야 한다)
# from functools import reduce
# reduce(함수, 반복가능한객체)
## def로 reduce 사용하기
from functools import reduce a = [1, 2, 3, 4, 5] def bbb (x, y): return x+y print(reduce(bbb, a)) :: 15
## 함수 bbb에서 x + y를 반환하도록 만들었으므로 reduce는 그림과 같이 요소 두 개를 계속 더하면서 결과를 누적한다
## 람다 표현식으로 reduce 사용하기
a = [1, 2, 3, 4, 5] from functools import reduce c = reduce(lambda x, y : x+y, a) print(c) :: 15
# 참고 | map, filter, reduce와 리스트 표현식
## 리스트(딕셔너리, 세트) 표현식으로 처리할 수 있는 경우에는 map, filter와 람다 표현식 대신 리스트 표현식을 사용하는 것이 좋습니다. list(filter(lambda x: x > 5 and x < 10, a))는 다음과 같이 리스트 표현식으로도 만들 수 있습니다.
<IDLE> a = [8, 3, 2, 10, 15, 7, 1, 9, 0, 11] [i for i in a if i > 5 and i < 10] :: [8, 7, 9]
### 리스트 표현식이 좀 더 알아보기 쉽고 속도도 더 빠릅니다.
## 또한, for, while 반복문으로 처리할 수 있는 경우에도 reduce 대신 for, while을 사용하는 것이 좋다.
왜냐하면 reduce는 코드가 조금만 복잡해져도 의미하는 바를 한 눈에 알아보기가 힘들다.
이러한 이유로 파이썬 3부터는 reduce가 내장 함수에서 제외되었다.
# reduce(lambda x, y: x + y, a)는 다음과 같이 for 반복문으로 표현할 수 있습니다.
<IDLE> a = [1, 2, 3, 4, 5] x = a[0] for i in range(len(a) - 1): ... x = x + a[i + 1] ... x :: 15
728x90'TIL' 카테고리의 다른 글
TIL.30 클래스와 메서드 사용하기 (0) 2020.11.07 TIL. 29 전역 변수, 지역변수, 클로저 알아보기 (0) 2020.11.06 TIL. 27 재귀 호출(recursive call) (0) 2020.11.04 TIL.26 함수 매개변수 및 인수 (0) 2020.11.03 TIL. 25 함수의 호출 과정 (0) 2020.11.02