#!/usr/bin/env python # coding: utf-8 # *** # *** # # 16. 람다 함수 # *** # *** # --- # ## 1. 람다(lambda) 함수 정의 # --- # - 람다(lambda) 함수 (or 축약 함수): https://wikidocs.net/64 # - 일반적인 함수를 한 줄의 문(Statement)으로 정의할 수 있는 새로운 함수 정의 리터럴 # - 함수 몸체에는 식(expression)만이 올 수 있다. # - 대부분의 경우 함수 이름을 정의하지 않으면서 일회성으로 활용할 함수를 정의할 때 활용 # - 구문(syntax) # - lambda 콤마로 구분된 인수들: 식(expression) # ### 1-1 람다 함수 정의 예 # - 인수가 한 개 있는 람다 함수 # In[2]: f = lambda x: x + 1 print(f(1)) # - 인수가 두 개 있는 람다 함수를 지니는 변수 지정 및 함수 호출 # In[3]: g = lambda x, y: x + y print(g(1, 2)) # - 기본 인수를 지니는 람다 함수 정의 # In[4]: incr = lambda x, inc = 1: x + inc print(incr(10))#inc 기본 인수 값으로 1 사용 print(incr(10, 5)) # - 가변 인수를 지니는 람다 함수 정의 # In[2]: vargs = lambda x, *args: args print(vargs(1, 2, 3, 4, 5)) # 이전 jupyter notebook 참고; "넣어주는 인수 값들 중 일반 인수에 할당되는 값을 제외한 나머지 값들을 지닌 튜플 객체가 할당된다." print(type(vargs)) print(type(vargs(1, 2, 3, 4, 5))) # ### 1-2 람다 함수 사용하기 # In[3]: def f1(x): return x * x + 3 * x - 10 def f2(x): return x * x * x def g(func): return [func(x) for x in range(-10, 10)] print(g(f1)) print(g(f2)) # In[4]: def g(func): return [func(x) for x in range(-10, 10)] print(g(lambda x: x * x + 3 * x - 10)) print(g(lambda x: x * x * x)) # - 람다 함수를 사용하는 코드 예제 # In[9]: # 더하기, 빼기, 곱하기, 나누기에 해당하는 람다 함수 리스트 정의 func_list = [ lambda x, y: x + y, lambda x, y: x - y, lambda x, y: x * y, lambda x, y: x / y ] def menu(): print("0. add") print("1. sub") print("2. mul") print("3. div") print("4. quit") return int(input('Select menu:')) while 1: sel = menu() if sel < 0 or sel > len(func_list): continue if sel == len(func_list): break x = int(input('First operand:')) y = int(input('Second operand:')) print('Result =', func_list[sel](x,y), end="\n\n") # *** # ## 2 람다 함수의 활용 # *** # - map, filter, reduce 내장 함수 # - 첫번째 인자: function # - 첫번째 인자는 일반적으로 람다 함수를 인자로 받는다. # - 두번째 인자: 시퀀스 자료형 (문자열, 리스트, 튜플) # ### 2-1 map 내장 함수 # - map(function, seq) # - (python2) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 결과를 동일 시퀀스 자료형으로 반환한다. # - (python3) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 원소를 지닌 map 객체를 반환한다. # - 이후 동일한 자료형으로 다시 변환 필요 # In[14]: def f(x): return x * x X = [1, 2, 3, 4, 5] m = map(f, X) print(type(m)) # In[10]: def f(x): return x * x X = [1, 2, 3, 4, 5] Y = list(map(f, X)) print(Y) # - map 내장 함수를 사용하지 않을 때 코드 # In[11]: def f(x): return x * x X = [1, 2, 3, 4, 5] Y = [] for x in X: y = f(x) Y.append(y) print(Y) # - map과 람다 함수를 동시에 사용하는 코드 (가장 추천하는 코드) # In[12]: X = [1, 2, 3, 4, 5] print(list(map(lambda x: x * x, X))) # - range(10)의 모든 값 x에 대해 f = x \* x + 4 * x + 5의 계산 결과를 리스트로 구함 # In[13]: Y = list(map(lambda x: x * x + 4 * x + 5, range(10))) print(Y) # - 각 단어들의 길이 리스트 # In[14]: y = list(map(lambda x: len(x), ["Hello", "Python", "Programming"])) print(y) # ### 2-2 filter 내장 함수 # - filter(function, seq) # - (python2) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 결과가 참인 원소값들만을 동일 시퀀스 자료형으로 반환한다. # - (python3) seq 시퀀스 자료형이 지닌 각 원소값들에 대해 function에 적용한 결과가 참인 원소값들만을 지닌 filter 객체를 반환한다. # - 이후 동일한 자료형으로 다시 변환 필요 # In[15]: print(list(filter(lambda x: x > 2, [1, 2, 3, 34]))) # - 위 코드는 아래와 동일하다. # In[16]: y = [] for x in [1, 2, 3, 34]: if x > 2: y.append(x) print(y) # - 주어진 시퀀스 내에 있는 정수중 홀수만 필터링 # In[17]: print(list(filter(lambda x: x % 2, [1, 2, 3, 4, 5, 6]))) # - 주어진 시퀀스 내에 있는 정수중 짝수만 필터링 # In[18]: print(list(filter(lambda x: x % 2 - 1, [1, 2, 3, 4, 5, 6]))) # - 특정 범위에 있는 정수만 필터링 # In[19]: def F(): x = 1 print(list(filter(lambda a: a > x, range(-5, 5)))) F() # ## python2 --> python3 # (python2) # - map과 filter의 결과는 주어진 seq 자료형과 동일함 # (python3) # - filter, map은 iterator 객체인 filter, map을 각각 리턴함 # - 참고 # - https://docs.python.org/3/library/functions.html#map # - https://docs.python.org/3/library/functions.html#filter # - https://stackoverflow.com/questions/12319025/filters-in-python3 # In[22]: print(filter(lambda x: x > 2, [1, 2, 3, 34])) print(filter(lambda x: x > 2, (1, 2, 3, 34))) print(filter(lambda x: x < 'a', 'abcABCdefDEF')) # In[24]: print(list(filter(lambda x: x > 2, [1, 2, 3, 34]))) print(tuple(filter(lambda x: x > 2, (1, 2, 3, 34)))) print(list(filter(lambda x: x < 'a', 'abcABCdefDEF'))) # ### 2-4 reduce 내장 함수 # - reduce (function, seq[, initial]) # - 파이썬3에서 reduce() 내장 함수 지원하지 않음. # - 파이썬3에서 reduce() 함수를 사용하려면 다음의 라인을 상단에 추가해주어야 한다. # - from functools import reduce # - seq 시퀀스 자료형이 지닌 원소값들에 대해 function 함수를 적용하면서 하나의 값으로 축약한다.(reduce returns a single value.) # - 첫번째 인자인 function 함수는 반드시 두 개의 인자 (예를 들어, x, y)를 받아야 한다. # - seq 시퀀스 자료형의 각 원소값들은 각 단계별로 y에 순차적으로 들어간다. # - 함수가 수행된 값은 각 단계별로 x에 순차적으로 들어간다. # - 추가적으로 제공가능한 세번째 인자인 initial은 첫번째 단계에 x에 할당할 초기값으로 사용된다. # - 참고: https://www.python-course.eu/python3_lambda.php # In[27]: from functools import reduce # In[28]: print(reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])) # | 단계 | x | y | reduce | # |-----|---|---|---------| # | 1 | 0 | 1 | 1 | # | 2 | 1 | 2 | 3 | # | 3 | 3 | 3 | 6 | # | 4 | 6 | 4 | 10 | # | 5 | 10| 5 | 15 | # - initial 값 할당 # In[33]: print(reduce(lambda x, y: x + y, [1, 2, 3, 4, 5], 100)) # - 1부터 10까지 각 수에 대한 제곱값을 모두 더한 결과 구함 # In[34]: print(reduce(lambda x, y: x + y * y, range(1, 11), 0)) # In[35]: x = 0 for y in range(1, 11): x = x + y * y print(x) # - 문자열 순서 뒤집기 # In[36]: print(reduce(lambda x, y: y + x, 'abcde')) # | 단계 | x | y | reduce | # |-----|---|---|---------| # | 1 | '' | 'a' | 'a' | # | 2 | 'a' | 'b' | 'ba' | # | 3 | 'ba' | 'c' | 'cba' | # | 4 | 'cba' | 'd' | 'dcba' | # | 5 | 'dcba' | 'e' | 'edcba' | # In[37]: lis = [1, 3, 5, 6, 2] print("The maximum element of the list is : ",end="") print(reduce(lambda a, b: a if a > b else b, lis)) #

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일