함수형 프로그래밍

2021. 3. 25. 14:14·[Language] - Python

개요


함수형 프로그래밍은 프로그램을 수학적 함수의 계산으로 바라보고 상태 변화와 가변 데이터를 최소화하는 프로그래밍 패러다임이다. 일급 시민(first citizen)을 객체 지향 프로그래밍에서는 객체 위주의 사고를 했었다면, 함수형 프로그래밍에서는 함수가 일급 시민이 된다. 즉, 함수를 객체처럼 특정 자료 구조에 담거나 함수의 인자로 전달하는 등의 행위가 가능하다. 함수형 프로그래밍은 아래와 같은 특징들이 있다.

 

순수 함수 (Pure Function)

def add(x, y):
    return x + y
  • 동일한 입력에 대해 항상 동일한 출력을 반환한다. 또한, 함수가 자신의 외부 상태를 변경하지 않으며 사이드 이펙트가 없어야 한다. 예를 들면, 함수 내부에서 전역 변수나 외부 데이터를 수정하지 않아야 한다.
  • 이로써 코드가 예측 가능해지고, 테스트와 디버깅이 수월하다.

 

불변성 (Immutable) 

original = [1, 2, 3]
new_list = original + [4]  # 원본 리스트는 변경되지 않음

# 불변성을 지키지 않는 예시
def add_item(lst, item):
    lst.append(item)  # 원본 리스트가 변경됨
    return lst

# 불변성을 지키는 예시
def add_item(lst, item):
    return lst + [item]  # 원본 리스트는 그대로, 새로운 리스트 반환
  • 함수형 프로그래밍에서 함수들은 원본 데이터를 수정하지 않고, 필요한 경우 새로운 데이터를 복사 및 생성한다. 이로써, 예측 가능한 코드와 안전한 상태 관리를 가능하게 한다.

 

고차 함수 (Higher-Order Function)

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

def increment(n):
    return n + 1

print(apply_twice(increment, 3))  # 5
  • 함수를 일급 객체로 받아들여, 함수 자체를 인자로 받거나 반환하는 형태를 지원한다.

이 외에도 익명 함수(Anonymous Function)과 지연 평가(Lazy Evaluation)과 같은 성질들도 존재한다.

 


 

Python에서 제공하는 고차 함수


Python에서는 map, reduce, filter과 같은 고차 함수와 lambda같은 익명 함수 표현식(lambda expression)을 통해 구현할 수 있다.

 

lambda

def add(x, y):
	return x + y

lambda x, y: x + y # <function <lambda> at 0x000001746FA62AE8>
(lambda x, y: x + y)(10, 20) # 30
  • Python의 lambda expression은 무명메소드로써 함수명 없이도 로직을 정의할 수 있다.
  • add 라는 함수명을 가진 함수를 정의하여 지속적으로 재사용할 수도 있지만, lambda 키워드 뒤로 받을 인자들과 콜론(:) 뒤로 반환될 값을 명시하여 무명 함수로 정의할 수 있다.

 

map

# map(function, iterable)
list(map(int, (0.1, 9.2, 4.3, 1.3))) # [0, 9, 4, 1]

 

  • map() 함수는 함수(function)과 순회 가능한 객체(iterable) 두 가지를 인자로 받는다. 인자로 받은 iterable의 각 원소마다 function을 적용하는 역할을 수행한다.
  • 즉, 위 코드에서는 int() 라는 정수형으로 변환해주는 캐스팅 함수(정확히는 int 클래스의 생성자)를 (0.1, 9.2, 4.3, 1.3) 튜플의 각 원소마다 호출해준 셈이 된다.
    • (int(0.1), int(9.2), int(4.3), int(1.3))

 

threshold = 0.5

list(map(lambda x: x > threshold, [0, 1, 1, 0, 1, 0])) # [False, True, True, False, True, False]
  • map() 함수의 첫 번째 인자로 함수가 올 수 있기 때문에 무명 함수(lambda expression)도 전달될 수 있다.
  • 위 코드는 0.5라는 임계치(threshold)를 정의하고, [0, 1, 1, 0, 1, 0] 리스트의 각 원소 x마다 theshold를 넘었으면 True, 못넘으면 False를 반환하는 람다 함수를 적용한 로직이다.

 

 

reduce

from functools import reduce 

'''
lambda x, y: print(x, y)
입력받은 두 값 x, y를 출력하고 아무것도 반환하지 않는 print 함수를 수행하는 람다 함수
'''
reduce(lambda x, y: print(x, y), [0, 1, 2, 3])

>>
0 1 # print 함수에 의해 0과 1을 출력했지만, print 함수 자체는 반환값이 없다. (None)
None 2 # 이전에 실행된 print 함수의 결과값(None)과 새로운 인자 2가 출력된다.
None 3 # 마찬가지로 None과 새로운 인자 3이 출력된다.
  • reduce()는 function의 리턴값에 누적하는 역할을 한다. 즉, function의 반환값을 다음에 실행될 function의 인자로 재귀적으로 전달하는 방식으로 동작한다.
  • 위 코드와 같이 print()를 호출으면 터미널(표준 출력)에 입력받은 값을 출력하지만 반환값이 없기때문에 None이 반환된다. 즉, return된 결과 None이 다음 loop에서 람다함수의 x 인자로 주입된다.
reduce(lambda x, y: x + y, [0, 1, 2, 3]) # 6

reduce(lambda x, y: x * y, [5, 1, 2, 3]) # 30
  • 첫 번째 reduce는 다음과 같이 동작한다.
    • 0과 1이 람다 함수 x, y로 주입되어 더해진 다음 1을 반환한다.
    • 반환된 1과 다음 원소인 2가 다시 람다 함수 x, y로 주입되어 더해진 다음 3을 반환한다.
    • 마찬가지로 반환된 3과 3이 람다 함수로 주입되어 6을 반환한다.
  • 두 번째 reduce는 (5 * 1) = 5  -> (5 * 2) = 10  -> (10 * 3) = 30

 

filter

filter(lambda x : x < 5, (4, 6)) # <filter object at 0x000001746FA78898>


list(filter(lambda x : x < 5, (4, 6, 1, 8))) # [4, 1]
  • filter()는 iterator에서 주어진 function의 조건에 부한하는 원소만 필터링하는 역할을 한다.
  • (4, 6, 1, 8) 튜플 중에서 각 원소가 x로 주입되면 5를 넘지 못하는 원소만 True를 반환하는 람다 함수에 의해 [4, 1]을 원소로 갖는 filter 객체를 리스트로 형변환한 결과가 나왔다.

'[Language] - Python' 카테고리의 다른 글

[Tip] win32com 모듈을 사용한 엑셀 제어  (0) 2021.04.20
제너레이터 (Generator)  (0) 2021.04.14
[Tip] if문 분기와 삼항연산자가 사용하기 싫을 때  (0) 2021.03.24
zip  (0) 2021.03.24
property 데코레이터  (8) 2021.02.02
'[Language] - Python' 카테고리의 다른 글
  • [Tip] win32com 모듈을 사용한 엑셀 제어
  • 제너레이터 (Generator)
  • [Tip] if문 분기와 삼항연산자가 사용하기 싫을 때
  • zip
Bebsae
Bebsae
  • Bebsae
    뱁새zip
    Bebsae
  • 전체
    오늘
    어제
    • 분류 전체보기 (108)
      • [DevOps] - Kubernetes (5)
      • [DevOps] - AWS (1)
      • [AI] - Machine Learning (19)
      • [AI] - Neural Network (7)
      • [CS] - Network (2)
      • [CS] - Data Structure (3)
      • [CS] - Design Pattern (6)
      • [Language] - Python (15)
      • [Library] - Numpy (7)
        • Quick Start (5)
        • API (2)
      • [Framework] - Django (3)
      • [Framework] - QGIS (6)
      • [Framework] - PyQT (4)
      • [Mathematics] - Linear Alge.. (14)
      • [Mathematics] - Statistical (2)
      • [ETC] - Python (3)
      • [ETC] - C++ (1)
      • [ETC] - Linux (1)
      • 논문 (5)
      • 회고록 (3)
      • 생산성 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    Linear
    교차검증
    선형대수
    decomposition
    Python
    디자인패턴
    linearalgebra
    Convolution
    분해
    파이썬
    MachineLearning
    DEEPLEARNING
    QGIS
    algebra
    RNN
    신경망
    Learning
    머신러닝
    numpy
    Machine
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Bebsae
함수형 프로그래밍
상단으로

티스토리툴바