규도자 개발 블로그

파이썬 람다(lambda)란? 본문

Python/Python

파이썬 람다(lambda)란?

규도자 (gyudoza) 2021. 4. 8. 18:17

파이썬 람다(lmbda)란

람다는 "익명함수"를 의미한다. 그럼 또 의문이 든다. 엥? 익명함수가 뭐냐? 익명함수는 함수는 함수인데 기존처럼 함수명을 명명하지 않고도 쓸 수 있는 함수를 의미한다.

 

기존 함수가

def sum_ab(a, b):
    return a + b

print(sum_ab(1, 2))
# 3

위와 같이 명명하고 사용하는 것과 달리 람다는

sum_lambda = lambda a, b: a + b
print(sum_lambda(1, 2))
# 3

이런식으로 변수에 할당해서 사용할 수도 있다.

근데 보통의 함수도 변수에 담아서 사용할 수 있다.

def sum_ab(a, b):
    return a + b
print(sum_ab(1, 2))
# 3
test = sum_ab
print(test(1, 2))
# 3

엥? 그럼 두개 별로 차이 없는 거 아냐? 라고 할 수도 있다. 맞다. 차이 없다. 그냥 람다는 함수를 편하게 쓰기 위한 축약형이라고 할 수 있다. 기존 함수나 람다나 그 본질은 차이가 없다. 단지 표현방식에만 차이가 있을 뿐이다.

 

그리고 특히나 이 람다의 축약성이 장점을 발휘하는 곳이 있다. 바로 map이나 filter, 그리고 sorted같은 함수이다.

 

map

map은 함수와 iterable한 데이터를 건네받아 iterable한 데이터에 모든 함수를 적용한 값을 반환해주는 아주 유용한 함수이다.

test_list = [1, 2, 3, 4, 5]
test = list(map(str, test_list))
print(test)
# ['1', '2', '3', '4', '5']

이렇게 test_list의 각 원소에 str함수가 적용된 것을 확인할 수 있다. 하지만 여기에서 짝수인 애들만 str함수를 적용시켜야한다고 생각해보자. 갑자기 골이 아파진다. 하지만 우리의 lambda를 이용하면 쉽게 해결할 수 있다.

test_list = [1, 2, 3, 4, 5]
test = list(map(lambda x: str(x) if x % 2 == 0 else x, test_list))
print(test)
# [1, '2', 3, '4', 5]

짠~ 이렇게 말이다. 물론 기존형태의 함수로도 본 기능을 구현할 수 있다.

def even_str_only(number):
    return str(number) if number % 2 == 0 else number
test_list = [1, 2, 3, 4, 5]
test = list(map(even_str_only, test_list))
print(test)
# [1, '2', 3, '4', 5]

이렇게 말이다. 하지만 딱 봤을때도 람다로 처리한 것이 가독성도 그렇고, 훨씬 간단해 보인다. 식이 함수 안에 싹 보이니까 말이다.

filter

필터 함수는 이름처럼 매개변수로 주어진 함수의 조건에 따라 데이터를 반환하거나 반환하지 않는 기능을 가진 함수이다. 위 케이스들과 비슷하게 구현해보자면... 짝수인 원소만 반환시켜보자.

test_list = [5, 4, 3, 2, 1]
test = list(filter(lambda x: x % 2 == 0, test_list))
print(test)
# [4, 2]

이렇게 짝수인 원소만 반환시켜봤다. 물론 위처럼 기존 함수의 모양대로도 구현할 수 있다.

def check_even(number):
    return True if number % 2 == 0 else False
test_list = [5, 4, 3, 2, 1]
test = list(filter(check_even, test_list))
print(test)
# [4, 2]

filter함수는 각 원소가 함수를 만났을 때 True면 반환하는 iterable한 자료형에 포함시키고, False면 포함시키지 않는 형태로 작동한다. 그래서 이런식으로 작성하면 위 람다를 썼을 때와 똑같이 작동한다.

sorted

마지막으로 sorted이다. dictionary자료형이 주어졌을 때 lambda를 이용하면 key값이 아닌 value값으로 정렬할 수 있기 때문이다.

test_dict = {
    'c': 3,
    'd': 2,
    'e': 1,
    'a': 5,
    'b': 4
}
print(test_dict)
# {'c': 3, 'd': 2, 'e': 1, 'a': 5, 'b': 4}
print(dict(sorted(test_dict.items())))
# {'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}

이렇게 비정렬된 dict가 있다고 생각해보자. 그래서 흔히 쓰는 방식인 sorted를 적용해서 정렬은 해봤는데 이번엔 value로 정렬해보고 싶다고 해보자.

print(dict(sorted(test_dict.items(), key=lambda x: x[1])))
# {'e': 1, 'd': 2, 'c': 3, 'b': 4, 'a': 5}

이런식으로 정렬이 된다. 물론! 이것도 일반함수처럼 명명하여 구현할 수 있다.

def sort_key(k_v):
    return k_v[1]
print(dict(sorted(test_dict.items(), key=sort_key)))
# {'e': 1, 'd': 2, 'c': 3, 'b': 4, 'a': 5}

이런식으로 말이다. dict.items()라는 함수는 dict에 담긴 자료형들을 각각 set에 담아 넘겨주는데 그것을 sort_key라는 함수에 담아서 반환해주는 1번 배열값(value값)을 기준으로 다시 정렬하여 반환해주는 것이라고 생각하면 쉽다.

 

 

결론! 람다는 그냥 함수이다. 기존의 함수들과 생긴 것만 다를 뿐이다. 대신 이걸 이용하면 보다 간결하게 많은 기능을 구현할 수 있다.

Comments