공부일지

[Python]itertools, functools, operator 개념과 함수형 프로그래밍과의 관계 본문

Computer/공부정리

[Python]itertools, functools, operator 개념과 함수형 프로그래밍과의 관계

이르리의 공부일지 2024. 9. 25. 20:55

작성일: 2024-09-25

 

 

 

Python을 통해서 컴퓨터 지식 익숙해지기가 요새 내 주안점이다.

itertools, functools, … 같은 외장 라이브러리들이 함수형 프로그래밍에 쓰인다는 걸 알게 됐다.

 

예전에는 ‘왜 functools, itertools 같은 이름을 가졌지? 그다지 와닿지 않는데..’ 라고 생각했었다.

그런데 위키독스 예제를 보다보니 기능에 이해가 가면서 이제는 생각이 바뀌었다.

아래 위키독스 목차에서 함수형 프로그래밍을 찾으면 자주 쓰이는 요긴한 기능 몇가지를 설명해준다.

거기서 functools, itertools, operator라는 외장 라이브러리가 포함되는 걸 확인할 수 있다.

 

c.f.

034 다양한 기준으로 정렬하려면? ― operator.itemgetter

 

034 다양한 기준으로 정렬하려면? ― operator.itemgetter

operator.itemgetter는 주로 sorted와 같은 함수의 key 매개변수에 적용하여 다양한 기준으로 정렬할 수 있도록 하는 모듈이다. ## 문제 학생의 이름, …

wikidocs.net

더보기

위키독스 참고

operator에서 쓸만한 것은 연산기능 외에

operator.itemgetter(item), operator.itemgetter(items)

가 있다.

itertools의 group by랑 연결해서 쓰기 좋음

 

 

그래서 '그 3가지가 함수형 프로그래밍 관련 도구들인가?' 했는데

공식문서 목차를 참고해보니 functools, itertools는 함수형 프로그래밍 기능을 하고,

opertaor는 연산자로서, 함수보다는 함수에 쓰이는 수식같은 개념이다.

비유하자면 functools, itertools는 수학에서 함수이고, Operator는 수학에서 연산자 역할을 하는 것이다.

물론 함수와 연산의 개념을 딱 자르기는 어렵겠지만 기능적으로 말이다.

 

c.f.

함수형 프로그래밍 HOWTO

 

Functional Programming HOWTO

Author, A. M. Kuchling,, Release, 0.32,. In this document, we’ll take a tour of Python’s features suitable for implementing programs in a functional style. After an introduction to the concepts of ...

docs.python.org

 

operator — Standard operators as functions

 

operator — Standard operators as functions

Source code: Lib/operator.py The operator module exports a set of efficient functions corresponding to the intrinsic operators of Python. For example, operator.add(x, y) is equivalent to the expres...

docs.python.org

 

 

 

 

함수형 프로그래밍


요약하자면,

  1. iterator에 대해 직관적인 연산
  2. return 값이 있어야하고, 전역변수같은 외부의 값에 영향받지 않아야함(=parameter나 지역변수에 의해서만 영향을 받음)
  3. ⇒ 예측가능한 반환값 ⇒ 병렬처리에 용이한 함수(이유: 반환값 명확해서 안전하게 쓸 수 있음)

 

참고 개념

고차함수  Higher Order Function

함수를 인자로 받고 함수를 반환할 수 있는 함수를 의미하며, 이는 일반 함수들이 자료형을 반환하는데 그치는 것과 구별된다.

 

순수함수  Pure Function

지역변수나 parameter같은 input이 아닌 다른 상태나 변수에 의해 반환값이 영향받지 않는 함수

 

 

아래는 GPT를 통해 함수형 프로그래밍에 대한 설명을 요청한 결과이다.

이를 통해 위 3가지 요약이 도출되었다.

예제를 참고해봅시다.

 

 

GPT

함수형 프로그래밍의 개념을 더 쉽게 이해하기 위해, 아래에 장단점을 보여주는 구체적인 예시를 들어 설명하겠습니다.

함수형 프로그래밍의 예시

1. 고차 함수와 간결함

함수형 프로그래밍에서는 map()이나 filter() 같은 고차 함수를 사용해 데이터를 간결하게 처리할 수 있습니다.

예시: 절차적 프로그래밍 방식

# 주어진 리스트의 숫자들을 제곱한 값을 새 리스트로 반환하는 절차적 방식
numbers = [1, 2, 3, 4, 5]
squares = []
for num in numbers:
    squares.append(num ** 2)
print(squares)

함수형 프로그래밍 방식

# map() 함수를 사용해 간결하게 제곱 처리
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))
print(squares)
  • 장점: 함수형 프로그래밍 방식은 코드가 훨씬 간결하고 직관적입니다.
  • 단점: 함수형 패러다임에 익숙하지 않은 사람에게는 처음엔 다소 생소할 수 있습니다.

 

2. 부수 효과 없는 순수 함수

함수형 프로그래밍에서는 함수의 입력이 동일하면 항상 동일한 출력을 반환하는 순수 함수를 지향합니다. 이는 디버깅과 테스트에 용이하게 합니다.

예시: 순수 함수

# 순수 함수는 함수 외부의 상태를 변경하지 않고, 항상 동일한 입력에 대해 동일한 출력을 반환
def add(a, b):
    return a + b

print(add(2, 3))  # 항상 5를 반환

예시: 비순수 함수

# 비순수 함수는 외부 상태를 변경할 수 있어, 테스트와 디버깅이 어려울 수 있음
result = 0

def add_to_result(value):
    global result
    result += value

add_to_result(5)
print(result)  # 외부 상태 'result'가 변경됨
  • 장점: 순수 함수는 상태를 변경하지 않기 때문에 코드를 추적하고 예측하기가 훨씬 쉽습니다.
  • 단점: 모든 상황에서 상태 변화를 완전히 배제하는 것이 어렵고, 특정 작업에는 불편할 수 있습니다.

 

3. 병렬 처리 용이성

함수형 프로그래밍은 부수 효과가 없기 때문에 병렬 처리에서 안전하게 사용할 수 있습니다.

예시: 병렬 처리 가능한 함수형 코드

import multiprocessing

# 순수 함수를 병렬로 처리
def square(x):
    return x ** 2

numbers = [1, 2, 3, 4, 5]
with multiprocessing.Pool(5) as pool:
    result = pool.map(square, numbers)
print(result)

여기서 square() 함수는 순수 함수이기 때문에, 여러 프로세스에서 동시에 실행해도 안전합니다.

  • 장점: 상태를 변경하지 않는 함수는 병렬 처리를 하기에 매우 적합하여, 성능 최적화에 유리합니다.
  • 단점: 복잡한 병렬 처리가 필요한 경우, 함수형 코드의 흐름을 이해하기 어려울 수 있습니다.

 

4. 재사용성과 모듈성

함수형 프로그래밍은 작은 함수들로 코드를 분리하기 때문에 재사용성이 높습니다.

예시: 재사용 가능한 작은 함수들

def is_even(n):
    return n % 2 == 0

def double(n):
    return n * 2

numbers = [1, 2, 3, 4, 5]
even_numbers = list(filter(is_even, numbers))  # 짝수만 필터링
doubled_numbers = list(map(double, even_numbers))  # 짝수를 두 배로
print(doubled_numbers)
  • 장점: 각 함수가 독립적으로 동작하므로, 필요한 곳에서 재사용할 수 있고 유지보수가 쉽습니다.
  • 단점: 너무 작은 함수들로 분리하면 코드가 분산되어 전체 흐름을 파악하기 어려울 수 있습니다.

 

 

Operator와 함수형 프로그래밍과의 관계


Python의 operator 모듈은 함수형 프로그래밍과 밀접하게 관련이 있습니다.

operator 모듈은 일반적으로 사용하는 연산자(예: +, -, *, ==, 등)를 함수로 사용할 수 있도록 제공하는 도구입니다.

이는 함수형 프로그래밍에서 고차 함수와 같은 기능과 잘 어울립니다.

 

operator 모듈과 함수형 프로그래밍의 관계

함수형 프로그래밍에서는 함수가 일급 객체이기 때문에 함수를 변수에 저장하거나, 다른 함수에 인수로 전달하거나, 함수에서 반환할 수 있습니다. 이때 operator 모듈은 일반적인 연산자들을 함수로 표현하여 이런 패러다임에 맞춰 쉽게 사용할 수 있게 해줍니다.

 

예시: operator 모듈을 사용한 함수형 프로그래밍

import operator

# 일반적인 더하기 연산
result = operator.add(5, 3)
print(result)  # 출력: 8

# 리스트 요소들의 곱을 구하는 고차 함수 사용 예시
from functools import reduce

numbers = [1, 2, 3, 4]
result = reduce(operator.mul, numbers)
print(result)  # 출력: 24

위 예시에서 operator.add와 operator.mul은 각각 +와 * 연산자를 함수로 사용한 것입니다. 이러한 함수들은 고차 함수(reduce, map, filter 등)에 전달하여 사용할 수 있으며, 이는 함수형 프로그래밍 스타일과 잘 맞습니다.

 

operator 모듈의 주요 함수들

  • 비교 연산자: operator.eq, operator.ne, operator.lt, operator.le, operator.gt, operator.ge
  • 수학 연산자: operator.add, operator.sub, operator.mul, operator.truediv, operator.floordiv, operator.mod, operator.pow
  • 논리 연산자: operator.and_, operator.or_, operator.not_
  • 속성/아이템 접근: operator.attrgetter, operator.itemgetter

 

 

돌아보며


이번 기회에 함수형 프로그래밍의 개념이 다소 명확해졌다.

현재 concurrent.futures.pool의 ThreadPoolExecutor를 쓰며 병렬처리를 통해

데이터 클렌징을 빠르게 진행하고 있는데

이 때 Python의 고차함수인 map이 쓰이고 있다.

전에는 그냥 'map'이었는데, 이제는 어디 출신인지 알고 쓸 수 있겠다.