#!/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))
x = 1
x += 1
# - 인수가 두 개 있는 람다 함수를 지니는 변수 지정 및 함수 호출
# In[2]:
g = lambda x, y: x + y
print(g(1, 2))
# - 기본 인수를 지니는 람다 함수 정의
# In[3]:
incr = lambda x, inc = 1: x + inc
print(incr(10))#inc 기본 인수 값으로 1 사용
print(incr(10, 5))
# - 가변 인수를 지니는 람다 함수 정의
# In[4]:
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[5]:
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[7]:
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[8]:
# 더하기, 빼기, 곱하기, 나누기에 해당하는 람다 함수 리스트 정의
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[1]:
def f(x):
return x * x
X = [1, 2, 3, 4, 5]
m = map(f, X)
print(type(m))
print(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[3]:
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)))
# 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[4]:
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일