비즈니스 문제를 해결하고 예측하는 데이터 사이언티스트가 되고 싶다면?
#인공지능 

람다 표현식과 자주 쓰이는 함수들, map(), filter(), reduce()

람다 표현식에 대해 알아보고, 함께 자주 쓰이는 map(), filter(), reduce()가 무엇인지 알아보고, 왜 실전에서 사용되고, 어떻게 사용해야 잘 사용할 수 있을 지 실습을 통해서 이해해보자.

2024-05-31 | 이태환

람다 표현식과 자주 쓰이는 함수들

람다 표현식(lambda expression)은 익명 함수로, 함수 이름 없이 간단하게 함수를 정의할 수 있는 방법입니다. 특히 람다는 map(), filter(), reduce()와 같은 함수와 결합하여 코드의 간결성을 극대화할 수 있습니다. 이번 포스트에서는 이러한 함수들을 람다 표현식과 함께 사용하는 방법을 알아보겠습니다.

1. 람다 표현식이란?

람다 표현식은 간단히 말해 이름이 없는 함수입니다. 람다 표현식은 다음과 같은 형태로 작성됩니다:

lambda 인수1, 인수2, ... : 표현식

여기서 인수1, 인수2, ...는 함수에 입력으로 들어가는 값들을 의미하며, 표현식은 반환될 값을 정의합니다.

예시: 더하기 함수

# 일반 함수 정의
def add(x, y):
    return x + y

# 람다 표현식으로 정의
add_lambda = lambda x, y: x + y

# 사용 예시
print(add_lambda(10, 20))  # 출력: 30

실무에서 자주 사용하는 이유

람다 표현식은 코드의 간결성을 높여줍니다. 특히 단순한 연산이나 변환을 수행할 때, 일회성으로 사용할 함수를 정의할 필요 없이 람다 표현식을 사용하여 즉석에서 정의할 수 있습니다. 이는 코드의 가독성을 높이고 유지보수를 쉽게 합니다.

장점

  • 간결성: 짧은 코드로 간단한 함수를 정의할 수 있습니다.
  • 익명성: 이름이 필요 없는 함수로, 일회성으로 사용할 때 유용합니다.
  • 즉시 사용 가능: 정의와 동시에 사용할 수 있습니다.

단점

  • 가독성 저하: 복잡한 람다 표현식은 오히려 가독성을 떨어뜨릴 수 있습니다.
  • 디버깅 어려움: 익명 함수이기 때문에 디버깅 시 함수 이름을 통한 추적이 어렵습니다.

 

2. map() 함수

map() 함수는 입력받은 iterable의 각 요소에 함수를 적용한 결과를 반환합니다.

예시: 리스트의 각 요소에 2를 곱하기

# 일반 함수 사용
def list_mul(x):
    return x * 2

result = list(map(list_mul, [1, 2, 3]))
print(result)  # 출력: [2, 4, 6]

# 람다 표현식 사용
result = list(map(lambda x: x * 2, [1, 2, 3]))
print(result)  # 출력: [2, 4, 6]

실무에서 자주 사용하는 이유

map() 함수는 데이터 변환 작업에 유용합니다. 예를 들어, 대규모 데이터셋의 각 항목에 동일한 변환을 적용해야 할 때, map()을 사용하면 반복문을 사용하는 것보다 더 간결하고 명확한 코드를 작성할 수 있습니다. 이는 특히 데이터 처리와 분석 작업에서 자주 사용됩니다.

실무 예시

# 예시: 사용자 입력 데이터를 정수 리스트로 변환
user_inputs = ["42", "13", "99", "0"]
int_inputs = list(map(int, user_inputs))
print(int_inputs)  # 출력: [42, 13, 99, 0]

# 예시: 사용자 정보에서 나이만 추출
users = [
    {"name": "Alice", "age": 28},
    {"name": "Bob", "age": 23},
    {"name": "Charlie", "age": 35}
]
ages = list(map(lambda user: user["age"], users))
print(ages)  # 출력: [28, 23, 35]

장점

  • 간결성: 반복문 없이 각 요소에 함수 적용 가능.
  • 일관성: 일괄적으로 동일한 변환을 적용할 수 있습니다.
  • 명확성: 변환 과정이 코드로 명확히 드러납니다.

단점

  • 가독성 저하: 복잡한 변환일 경우 가독성이 떨어질 수 있습니다.
  • 추가 메모리 사용: 변환 결과를 새로운 리스트로 만들기 때문에 메모리 사용이 증가할 수 있습니다.

3. filter() 함수

filter() 함수는 iterable의 각 요소에 함수를 적용하여 반환 값이 True인 요소들만 모아 새로운 iterable을 만듭니다.

예시: 리스트에서 홀수만 필터링

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 일반 함수 사용
def is_odd(x):
    return x % 2 != 0

result = list(filter(is_odd, nums))
print(result)  # 출력: [1, 3, 5, 7, 9]

# 람다 표현식 사용
result = list(filter(lambda x: x % 2 != 0, nums))
print(result)  # 출력: [1, 3, 5, 7, 9]

실무에서 자주 사용하는 이유

filter() 함수는 조건에 따라 데이터를 필터링할 때 매우 유용합니다. 데이터셋에서 특정 조건을 만족하는 항목들만 추출해야 할 때, filter()를 사용하면 조건문을 반복해서 사용할 필요 없이 간결하게 코드를 작성할 수 있습니다.

실무 예시

# 예시: 특정 조건을 만족하는 데이터 필터링
employees = [
    {"name": "John", "age": 25, "department": "HR"},
    {"name": "Jane", "age": 30, "department": "Finance"},
    {"name": "Dave", "age": 22, "department": "Engineering"},
    {"name": "Anna", "age": 28, "department": "Marketing"}
]

# 25세 이상인 직원 필터링
adult_employees = list(filter(lambda x: x["age"] >= 25, employees))
print(adult_employees)
# 출력: [{'name': 'John', 'age': 25, 'department': 'HR'}, {'name': 'Jane', 'age': 30, 'department': 'Finance'}, {'name': 'Anna', 'age': 28, 'department': 'Marketing'}]

# 예시: 특정 부서의 직원 필터링
engineering_employees = list(filter(lambda x: x["department"] == "Engineering", employees))
print(engineering_employees)
# 출력: [{'name': 'Dave', 'age': 22, 'department': 'Engineering'}]

장점

  • 간결성: 조건을 명확하게 정의하여 필터링 가능.
  • 효율성: 조건을 만족하는 요소만 추출하여 처리 효율성을 높일 수 있습니다.

단점

  • 가독성 저하: 복잡한 조건일 경우 가독성이 떨어질 수 있습니다.
  • 유연성 부족: 복잡한 필터링 조건을 조합할 때 다소 제한적일 수 있습니다.

4. reduce() 함수

reduce() 함수는 iterable의 요소들을 누적하여 하나의 값을 반환합니다. reduce() 함수는 functools 모듈에서 가져와야 합니다.

예시: 리스트 요소의 합 계산

from functools import reduce

# 일반 함수 사용
def sum_func(x, y):
    return x + y

result = reduce(sum_func, [1, 2, 3, 4])
print(result)  # 출력: 10

# 람다 표현식 사용
result = reduce(lambda x, y: x + y, [1, 2, 3, 4])
print(result)  # 출력: 10

실무에서 자주 사용하는 이유

reduce() 함수는 누적 계산이 필요할 때 유용합니다. 예를 들어, 리스트의 모든 요소를 합산하거나 곱할 때, reduce()를 사용하면 반복문보다 간결하게 코드를 작성할 수 있습니다. 이는 특히 집계 연산에서 자주 사용됩니다.

실무 예시

from functools import reduce

# 예시: 리스트 요소의 곱 계산
nums = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, nums)
print(product)  # 출력: 24

# 예시: 매출 데이터의 총 매출 계산
sales = [
    {"date": "2023-01-01", "amount": 1500},
    {"date": "2023-01-02", "amount": 2300},
    {"date": "2023-01-03", "amount": 1800}
]

total_sales = reduce(lambda x, y: x + y["amount"], sales, 0)
print(total_sales)  # 출력: 5600

장점

  • 간결성: 누적 연산을 간결하게 표현할 수 있습니다.
  • 일관성: 동일한 연산을 반복하여 일관된 결과를 얻을 수 있습니다.
  • 유연성: 다양한 누적 연산을 손쉽게 구현할 수 있습니다.

단점

  • 가독성 저하: 복잡한 연산일 경우 가독성이 떨어질 수 있습니다.
  • 초기값 필요: 초기값이 필요한 경우 이를 명시적으로 지정해야 합니다.
  • 디버깅 어려움: 중간 결과를 확인하기 어려워 디버깅이 어려울 수 있습니다.

 

마치며

람다 표현식과 map(), filter(), reduce() 함수들을 활용하면 코드가 훨씬 간결해지고 직관적이 됩니다. 람다 표현식을 사용하여 코드를 작성할 때는 가독성을 고려해야 하며, 너무 복잡한 표현식은 오히려 코드를 이해하기 어렵게 만들 수 있습니다. 이러한 점을 유의하면서 람다 표현식을 활용해 보세요!

 

참고할만한 페이지

3.5 람다(lambda) – 왕초보를 위한 Python: 쉽게 풀어 쓴 기초 문법과 실습 (wikidocs.net)

국민내일배움카드 발급은 어떻게 하고, 사용은 어떻게 해? : 2024년 최신 ‘내배카’ 가이드 – 모두의연구소 (modulabs.co.kr)