본문 바로가기
프로그래밍/파이썬

파이썬 - 람다 함수와 함수형 프로그래밍 기초

by ennak 2024. 12. 1.
반응형

람다 함수의 개념과 기본 구조

파이썬에서 람다 함수는 익명 함수를 생성하는 강력한 도구다.
이 함수는 단일 표현식으로 구성되며, 간결하고 일회성 사용에 적합하다. 람다 함수의 기본 구조는 다음과 같다.

lambda 인자: 표현식

 

예를 들어, 두 수를 더하는 람다 함수는 다음과 같이 작성할 수 있다

add = lambda x, y: x + y
result = add(3, 5)  # 결과: 8

 

이 예시에서 lambda x, y: x + y는 두 인자 x와 y를 받아 그 합을 반환하는 익명 함수를 정의한다.
이 함수를 변수 add에 할당하여 일반 함수처럼 사용할 수 있다.

람다 함수의 특징과 장점

1. 간결성

람다 함수는 일반 함수에 비해 매우 간결하게 작성할 수 있다. 특히 한 줄로 표현 가능한 간단한 연산에 유용하다.

2. 익명성

이름이 필요 없기 때문에, 일회성으로 사용되는 함수를 정의할 때 유용하다.

3. 함수형 프로그래밍 지원

람다 함수는 함수형 프로그래밍의 핵심 개념인 고차 함수(higher-order functions)를 쉽게 구현할 수 있게 해준다.

4. 가독성 향상

적절히 사용된 람다 함수는 코드의 의도를 더 명확하게 표현할 수 있다.

 

람다 함수의 활용

람다 함수는 다양한 상황에서 활용될 수 있다. 특히 Python의 map(), filter(), sorted() 함수와 함께 사용될 때 그 유용성이 돋보인다.

1. map() 함수와 람다

map() 함수는 iterable의 모든 요소에 함수를 적용하고 그 결과를 반환한다. 람다 함수와 함께 사용하면 코드를 더욱 간결하게 만들 수 있다.

numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared)  # 출력: [1, 4, 9, 16, 25]

 

2. filter() 함수와 람다

filter() 함수는 iterable의 요소 중 특정 조건을 만족하는 요소만 선택한다. 람다 함수를 사용하여 조건을 간단하게 정의할 수 있다.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 출력: [2, 4, 6, 8, 10]

 

3. sorted() 함수와 람다

sorted() 함수는 iterable을 정렬할 때 사용된다. 람다 함수를 key 인자로 사용하여 복잡한 정렬 기준을 쉽게 정의할 수 있다.

students = [('Alice', 22), ('Bob', 19), ('Charlie', 24)]
sorted_students = sorted(students, key=lambda x: x[1])
print(sorted_students)  # 출력: [('Bob', 19), ('Alice', 22), ('Charlie', 24)]

 

함수형 프로그래밍의 기초

함수형 프로그래밍은 계산을 수학적 함수의 평가로 취급하고 상태 변경과 가변 데이터를 피하는 프로그래밍 패러다임이다. 파이썬은 완전한 함수형 언어는 아니지만, 많은 함수형 프로그래밍 개념을 지원한다.

 

4-1. 순수 함수 (Pure Functions)

순수 함수는 동일한 입력에 대해 항상 동일한 출력을 반환하며, 부작용(side effects)이 없는 함수를 말한다. 이는 함수의 예측 가능성과 테스트 용이성을 높인다.

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

 

4-2. 불변성 (Immutability)

함수형 프로그래밍에서는 데이터의 불변성을 중요시한다. 이는 한 번 생성된 데이터를 변경하지 않고, 대신 새로운 데이터를 생성하는 방식을 의미한다.

# 불변성을 유지하는 방식
original_list = [1, 2, 3]
new_list = original_list + [4]  # 새로운 리스트 생성

 

4-3. 고차 함수 (Higher-Order Functions)

고차 함수는 다른 함수를 인자로 받거나 함수를 반환하는 함수를 말한다. 파이썬의 map(), filter(), reduce() 등이 대표적인 예시다.

def apply_twice(func, arg):
    return func(func(arg))

def add_five(x):
    return x + 5

result = apply_twice(add_five, 10)
print(result)  # 출력: 20

 

4-4. 재귀 (Recursion)

재귀는 함수가 자기 자신을 호출하는 프로그래밍 기법이다. 함수형 프로그래밍에서는 루프 대신 재귀를 사용하여 반복적인 작업을 수행하는 경우가 많다.

def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n-1)

print(factorial(5))  # 출력: 120

 

4-5. 함수 컴포지션 (Function Composition)

함수 컴포지션은 여러 함수를 조합하여 새로운 함수를 만드는 기법이다. 이를 통해 복잡한 연산을 더 작고 재사용 가능한 함수들의 조합으로 표현할 수 있다.

def compose(f, g):
    return lambda x: f(g(x))

def double(x):
    return x * 2

def increment(x):
    return x + 1

double_then_increment = compose(increment, double)
print(double_then_increment(5))  # 출력: 11

 

함수형 프로그래밍의 장점

1. 코드의 간결성과 가독성

함수형 프로그래밍은 복잡한 로직을 간결하고 표현력 있는 코드로 작성할 수 있게 해준다.

2. 테스트와 디버깅의 용이성

순수 함수와 불변성 원칙은 코드의 예측 가능성을 높이고, 따라서 테스트와 디버깅이 더 쉬워진다.

3. 병렬 처리의 용이성

부작용이 없는 순수 함수는 병렬 처리에 적합하다.

4. 모듈화와 재사용성

작은 순수 함수들을 조합하여 복잡한 로직을 구현할 수 있으므로, 코드의 모듈화와 재사용성이 향상된다.

 

파이썬에서의 함수형 프로그래밍 실전 예제

1. 리스트 컴프리헨션 (List Comprehension)

리스트 컴프리헨션은 함수형 프로그래밍의 개념을 활용한 파이썬의 강력한 기능이다.

# 1부터 10까지의 숫자 중 짝수의 제곱을 계산
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(even_squares)  # 출력: [4, 16, 36, 64, 100]

 

2. functools 모듈 활용

functools 모듈은 함수형 프로그래밍을 지원하는 여러 도구를 제공한다.

from functools import reduce

# 리스트의 모든 요소를 곱하는 함수
def multiply_list(numbers):
    return reduce(lambda x, y: x * y, numbers)

print(multiply_list([1, 2, 3, 4, 5]))  # 출력: 120

 

3. 데코레이터 (Decorator)

데코레이터는 함수를 수정하지 않고 기능을 확장할 수 있는 강력한 도구다.

참조: 2024.12.01 - [프로그래밍/파이썬] - 파이썬 - 데코레이터(Decorator)의 이해와 구현

def logger(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} returned: {result}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

add(3, 5)
# 출력:
# Calling function: add
# Function add returned: 8

 

4. 제너레이터 (Generator)

제너레이터는 이터레이터를 생성하는 함수로, 메모리 효율성을 높이는 데 사용된다.

참조: 2024.11.28 - [프로그래밍/파이썬] - 파이썬 - 제너레이터

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
for _ in range(10):
    print(next(fib), end=' ')
# 출력: 0 1 1 2 3 5 8 13 21 34

 

함수형 프로그래밍의 한계와 주의점

함수형 프로그래밍은 많은 장점을 가지고 있지만, 모든 상황에 적합한 것은 아니다. 다음과 같은 한계와 주의점을 고려해야 한다.

1. 러닝커브

함수형 프로그래밍은 전통적인 명령형 프로그래밍과는 다른 사고방식을 요구하므로, 초보자에게는 러닝커브가 가파를 수 있다.

2. 성능 이슈

일부 경우에 함수형 접근 방식은 명령형 접근 방식보다 성능이 떨어질 수 있다. 특히 재귀를 과도하게 사용할 경우 스택 오버플로우의 위험이 있다.

3. 가독성 문제

람다 함수나 고차 함수를 과도하게 사용하면 오히려 코드의 가독성이 떨어질 수 있다.

4. 상태 관리의 어려움

순수한 함수형 프로그래밍에서는 상태 변경을 피하므로, 상태 관리가 필요한 복잡한 애플리케이션에서는 구현이 어려울 수 있다.

반응형