람다 함수를 볼 때면 람바다 노래를 흥얼거리게 된다.
(분명 나만 그런거 아닐거라고 생각한다.)
자 그래서 람다란,
def
와 동일한 역할. def
를 사용해야할 정도로 복잡하지 않거나 def
를 사용할 수 없는 곳에 주로 쓰임런타임에 생성해서 사용할 수 있는 익명 함수
아래 코드는 내가 원래 알던 함수 작성법 & 함수 실행 결과
>>> def add(a, b):
return a+b
>>> result = add(3, 4)
>>> print(result)
7
같은 코드를 람다로 적으면 이렇게 아래와 같이 간결하게 적히고
같은 결과 값을 볼 수 있다.
>>> add = lambda a, b: a+b
>>> result = add(3, 4)
>>> print(result)
7
lambda
lambda 매개변수1, 매개변수2, ... : 매개변수를 사용한 표현식
람다 함수의 특징 중에는
리스트로 넣어 사용이 가능하다는 점이 있다.
다음의 코드를 보자.
>>> lambdas = [lambda x:x+10, lambda x:x+100]
>>> print(lambdas[0](5))
>>> 15
>>> print(lambdas[1](5))
>>> 105
람다 함수를 리스트의 요소값처럼 사용하였다.
람다 함수를 이용하면 딕셔너리를 정렬할 수도 있다.
다음의 코드들을 보자.
먼저, 아래의 코드는 람다를 사용하지 않을 때의 가장 기본적인 딕셔너리 정렬 방법이다.
fruit = {'apple':5, 'grape':10, 'banana':7, 'peach':3, 'melon':2}
def f1(x):
return x[0]
sorted1 = sorted(fruit.items(), key=f1)
# key, value 함께 출력하려면 .items() 사용 잊지 않기
print(sorted1)
>>> [('apple', 5), ('banana', 7), ('grape', 10), ('melon', 2), ('peach', 3)]
# key를 기준으로 abc 순서에 맞추어 정렬되었다.
# 왜냐하면, f1(x)함수 정의 시, return 값을 x[0]으로 설정해두었고,
# x[0]이란 결국 딕셔너리 요소 값의 key 값을 의미하기 때문이다.
# 만일, key값이 아니라 value값을 기준으로 정렬하고자한다면
# f1(x) 함수 정의 시, return 값을 x[1]로 설정하면
# [('melon', 2), ('peach', 3), ('apple', 5), ('banana', 7), ('grape', 10) ] 의 결과값을 볼 수 있을 것이다.
하지만 람다함수를 사용할 경우, 따로 함수를 만들지 않더라도 정렬이 가능하다.
fruit = {'apple':5, 'grape':10, 'banana':7, 'peach':3, 'melon':2}
sorted1 = sorted(fruit.items(), key=lambda x:x[0])
>>> [('apple', 5), ('banana', 7), ('grape', 10), ('melon', 2), ('peach', 3)]
# key를 기준으로 정렬
sorted2 = sorted(fruit.items(), key=lambda x:x[1])
>>> [('melon', 2), ('peach', 3), ('apple', 5), ('banana', 7), ('grape', 10) ]
# value를 기준으로 정렬
위처럼 람다 함수로 딕셔너리 정렬도 간단하게 한 줄로 할 수 있다.
sorted()
1)
myDict = {3:1,2:3,1:4} sorted(myDict.items(), key=lambda x:x[1]) >>>[(3, 1), (2, 3), (1, 4)] (value값 중심으로 정렬)
2)
myList = ["hello", "python", "hi"] sorted(myList, key=lambda x:x[1]) >>> ["hello", "hi", "python"] 출력 값: 문자열 요소 중 2번째 문자를 기준으로 정렬(각각 e, i, y)
map()
map()은 두 개의 인수를 가지는 함수이다.
r = map(funcion, iterable)
첫번째 인자인 function은 함수의 이름에 해당하며 iterable은 대표적으로 list, str, tuple등을 들 수 있겠다.
map()함수는 functiondp의해 변경된 iterator를 반환한다.
>>> a = [1, 2, 3, 4]
>>> b = [17, 12, 11, 10]
>>> list(map(lambda x, y: x+y, a, b))
[18, 14, 14, 14]
filter()
filter() 역시 두 개의 인수를 가지는 함수이다.
r = filter(function, iterable)
filter에 인자로 사용되는 function은 처리되는 각각의 요소에 대해 Boolean 값을 반환한다. True 반환 시 해당 요소는 남게되고 False 반환 시 해당 요소는 걸러져 제거된다.
>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
>>> list(filter(lambda x: x%3==0, foo))
[18, 9, 24, 12, 27]
reduce()
reduce()는 역시 두 개의 필수 인자와 하나의 옵션 인자를 가진다.
reduce()함수는 내장 함수가 아니므로 functools에서 reduce를 임포트하여 사용한다.
functools.reduce(function, iterable[, initializer])
아래 식을 보는 것이 빠르다.
약간 요소 하나하나를 먹어치우면서 줄여가는 느낌으로 실행한다.
>>> from functools import reduce
>>> reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
15
# 1+2, 3, 4, 5
# 1+2+3, 4, 5
# 1+2+3+4, 5
# 1+2+3+4+5
다음의 코드는 inc 함수로 lambda 함수를 즉석에서 생성하고 반환하는 함수를 정의한다. 작성된 함수들(f, g)은 인수 작성 시, 지정된 값만큼을 증가시켜 리턴한다.
>>> def inc(n):
return lambda x: x+n
>>> f = inc(2)
>>> g = inc(4)
>>> print(f(12))
14
# 위의 함수는 아래처럼 써도 그 리턴값이 같다
>>> print(inc(2)(12))
14
>>> print(g(12))
16
람다 자체도 함수인데 이런 람다를 품은 함수를 만들어보았다.
람다의 이 특성을 잘 활용하면 함수의 확장성이 상당히 좋을 것으로 예상된다.
다음과 같이 비밀번호의 길이와 대문자가 포함된 것을 확인하는 간단한 함수가 있다.
def check_password(password): if len(password) < 8: return 'SHORT_PASSWORD' if not any(c.isupper() for c in password): return 'NO_CAPITAL_LETTER_PASSWORD' return True
이 함수에 있는 if문 두 개를 람다표현식을 이용하여 다음과 같은 형식으로 작성해보자.
lambdas = [ ] def check_password_using_lambda(password): for f in lambdas: if f(password) is not None: return f(password) return True
참고로 람다 표현식을 사용한 결과는 다음과 같아야 한다.
>> print( check_password_using_lambda('123') ) SHORT_PASSWORD >> print( check_password_using_lambda('12356789f') ) NO_CAPITAL_LETTER_PASSWORD >> print( check_password_using_lambda('123456789fF') ) True
import types
Lambdas = [
lambda x : 'SHORT_PASSWORD' if len(x)<8 else None,
# lambda는 return을 쓰지 않으므로 return 값에 해당하는 값을
# 맨 앞에 문자열로 두고, 뒤에 조건을 쓴다. else None 이후 , 찍는 것도 잊지 말자
lambda x : 'NO_CAPITAL_LETTER_PASSWORD' if not any(i.isupper() for i in x) else None
# 여기서 헷갈렸던 것이 True 부분 리턴도 여기에 적어야 하나 하는 것이었다.
# 그 부분은 아래 실제 함수에 적어두자.
]
def check_password_using_lambda(x):
for f in Lambdas:
if f(x) is not None:
return f(x)
return True
결과 출력 시,
>>> print( check_password_using_lambda('123') )
SHORT_PASSWORD
>>> print( check_password_using_lambda('12356789f') )
NO_CAPITAL_LETTER_PASSWORD
>>> print( check_password_using_lambda('123456789fF') )
True
+) AWS Lambda라는 것도 있다는데, 다음번에는 그 부분도 공부해보자.
references:
https://www.youtube.com/watch?v=3zOypvH42jY (프로그래머 김플 스튜디오 람다1)
https://www.youtube.com/watch?v=h4HYbLs0LhM (프로그래머 김플 스튜디오 람다2)
https://blog.naver.com/timtaeil/221426580068 (sorted())
https://offbyone.tistory.com/73 (람다)