본문 바로가기
Python

[Py] Higher-order Function (고차함수)

by ds31x 2024. 11. 20.

정의

Higher-order function(고차 함수)란, 다음 조건 중 하나 이상을 충족하는 function를 가리킴:

  1. 다른 함수를 argument로 받을 수 있는 function
  2. 다른 함수를 반환할 수 있는 function
즉, Higher-order function이란
function을 다루는 function이라고 생각하면 됨.

 

original: https://medium.com/analytics-vidhya/higher-order-functions-python-716f508a8f41

 

Python에서는 function이 1급 객체(First-class object)이기 때문에,

  • function이 argument(인수)로 다른 function에 넘겨지거나,
  • 다른 function에서 return value(반환값)으로 사용되는 것이 가능함.

2023.07.15 - [Python] - [Python] first-class object (일급객체)

 

[Python] first-class object (일급객체)

함수형 프로그래밍 언어에서 중요한 개념이며, JavaScript와 Python등에서 Closure와 같은 다양한 디자인패턴을 응용 및 구현하는데 중요한 역할을 한다. 함수형 언어 관련 참고 자료 : http://ds31x.blogspot

ds31x.tistory.com


Higher-order Function(고차함수)의 특징

  1. function을 variable처럼 취급
    • function이 variable에 할당되거나
    • 다른 function에 argument로 전달될 수 있음.
  2. function의 조합 및 추상화 지원
    • 복잡한 연산을 간결하게 표현.
    • 주로 function을 return value로 반환.

High-order Function(고차 함수)의 예시

1. 다른 함수를 argument(인수)로 받는 Higher-order function

Python의 map, filter, reduce 등등.

 

map: 각 요소에 대해 지정된 함수를 적용하여 새로운 sequence를 얻음 .

nums = [1, 2, 3, 4]
squared = map(lambda x: x ** 2, nums)
print(list(squared))  # [1, 4, 9, 16]

filter: 조건을 만족하는 요소만을 포함한 sequence 반환.

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

reduce: 누적 계산 수행.

from functools import reduce
nums = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, nums)
print(product)  # 24

 

lambda expression(= annonymous function)과 같이 사용되는 경우가 많음.

2023.07.07 - [Python] - [Python] lambda expression and map, filter, reduce.

 

[Python] lambda expression and map, filter, reduce.

Python 에서 lambda function (or lambda expression)은 anonymous function(익명함수)를 만드는데 사용됨. function 형태로 code구현의 재사용을 해야하긴 하지만, def문을 이용하여 만들기에는 너무 간단한 경우 등에

ds31x.tistory.com


2. 다른 함수를 반환하는 Higher-order Function

Higher-order function은 function를 반환하여
새로운 기능을 가진 함수 를 만들 수 있음.


2-1. Closure 패턴

2023.07.15 - [Python] - [Python] Closure

 

[Python] Closure

Closure의 정의는 다음과 같음. Nested function 으로, 자신의 enclosing scope (= Python에서 non-local scope)의 상태값(lexcical environment의 variable 값)을 기억하고 유지, 변경, 사용할 수 있는 경우를 가르킴. 2023.07.1

ds31x.tistory.com

 

다음은 exponent를 다르게 설정한 제곱함수를 반환해주는 함수의 구현을 보여줌.

def power(exponent):
    def inner(base):
        return base ** exponent
    return inner

square = power(2)  # 제곱 함수 생성
cube = power(3)    # 세제곱 함수 생성

print(square(4))  # 16
print(cube(2))    # 8

2-2. Decorator

2023.08.18 - [Python] - [Python] Decorator

 

[Python] Decorator

Python이 제공하는 Decorator는 기존의 function을 수정하지 않으면서 특정 처리를 추가할 수 있게 해주는 도구라고 할 수 있다. Decorate의 "꾸미다"라는 의미에 맞게 기존 function을 꾸며주는 기능을 제공

ds31x.tistory.com

 

Decorator는 Higher-order function의 대표적인 사례임:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function call")
        result = func(*args, **kwargs)
        print("After function call")
        return result
    return wrapper

@my_decorator
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

이 외에 Python의 functools.partial, functools.singledispatch 등이 대표적인 사례임.


functools 모듈은 Python의 표준 라이브러리에 포함된 모듈로,
주로 고차 함수(higher-order function) 또는 함수형 프로그래밍 스타일을 구현하는 데
유용한 function들을 제공함.
즉, 이 모듈의 주요 목적은 함수와 관련된 작업을 쉽게 수행할 수 있도록 돕는 유틸함수를 제공하는 것임.

2-3. functools.partial

  • 특정 function의 특정 arguments를 미리 고정하여 새 함수를 생성하는 function.
  • 반복적으로 동일한 arguments를 전달해야 하는 경우 주로 이용됨.
from functools import partial

def multiply(x, y):
    return x * y

double = partial(multiply, y=2)  # y 값을 2로 고정
print(double(5))  # 10

2-4. functools.singledispatch

singledispatch는 첫번째 단일 인자 (=single) 타입을 기준으로 디스패치하는 overloading을 구현.

  • 일종의 generic function을 구현하는데 사용됨.
  • overloading을 python에서 가능하게 해줌.
    • 첫번째 argument의 type에 따라 다른 function호출이 가능해짐.
    • arguments의 조합에 따른 dispatch를 수행하는 multipledispatch가 아님을 주의
  • class의 메서드로도 사용가능하나, __init__에는 동작안함: 생성자를 위해선 singledispatchmethod 이용할 것.
참고로 "dispatch" 는 "전달하다, 분배하다, 할당하다" 등의 의미를 가지며,
프로그래밍에서는 특정 조건에 따라 실행할 함수를 선택 또는 호출하는 과정을 가리킴.
즉, type, value, 또는 다른 조건에 따라 function이나 method를 호출시키는 것을 가리킴.

 

다음은 argument가 int 인지 str인지에 따라 다르게 dispatch되는 function 을 구현한 예제임.

from functools import singledispatch

@singledispatch
def process(data):
    print("Default:", data)

@process.register(int)
def _(data):
    print("Processing int:", data)

@process.register(str)
def _(data):
    print("Processing str:", data)

process(10)       # Processing int: 10
process("hello")  # Processing str: hello
process([1, 2])   # Default: [1, 2]
  • register로 사용된 함수의 이름이 _로 쓰는 이유는 대부분 이후로 사용되지 않기 때문임.
  • 관례적으로 많이 사용되는 방식이나 강제 사항의 아니며 다음과 같이 구현해도 문제 없음.
from functools import singledispatch

@singledispatch
def process(data):
    print("Default:", data)

@process.register(int)
def process_int(data):
    print("Processing int:", data)

@process.register(str)
def process_string(data):
    print("Processing str:", data)

process(10)        # Processing int: 10
process("hello")   # Processing str: hello
process([1, 2, 3]) # Default: [1, 2, 3]

 

class에서의 method에 적용할 때는 singledispatchmethod를 사용하는 게 좋음
(생성자도 커버하는 장점을 가지나, Python 3.8이후부터만 지원됨.)

from functools import singledispatchmethod

class MyClass:
    @singledispatchmethod
    def __init__(self, arg):
        raise TypeError(f"Unsupported type: {type(arg)}")

    @__init__.register(str)
    def _(self, arg):
        print(f"Initialized with a string: {arg}")
        self.data = arg.upper()

    @__init__.register(int)
    def _(self, arg):
        print(f"Initialized with an integer: {arg}")
        self.data = arg * 10

# 사용 예시
obj1 = MyClass("hello")  # Initialized with a string: hello
print(obj1.data)         # HELLO

obj2 = MyClass(5)        # Initialized with an integer: 5
print(obj2.data)         # 50

obj3 = MyClass(3.14)     # TypeError: Unsupported type: <class 'float'>

3. Higher-order Function의 유용성

  • 코드 재사용성: 공통 패턴을 함수로 추출하여 재사용 가능.
  • 가독성 향상: 복잡한 연산을 간결하게 표현.
  • 유연성: 함수를 동적으로 생성하거나 조합 가능.

같이 보면 좋은 자료들

2023.10.06 - [Pages] - [Python] function 과 Scope, Name Space 정리

 

[Python] function 과 Scope, Name Space 정리

Function이란?https://dsaint31.me/mkdocs_site/CE/ch05/ch05_02_01_function/ BME228Function in the Programming Mathematics에서의 function과 약간의 차이점이 있으나 프로그래밍에서의 function은 많은 부분에서 Mathematics에서의 f

ds31x.tistory.com

https://medium.com/analytics-vidhya/higher-order-functions-python-716f508a8f41

 

Higher-Order Functions — Python

A programming language is said to support First Class Functions if it treats functions as first-class objects. By definition, a…

medium.com