Python 라이브러리 - functools

functools

공식 문서 링크

source code 링크

functools.cmp_to_key

functools.cmp_to_key(func)는 sorted()와 같은 정렬 함수의 key 매개변수에 함수(func)를 전달할 때 사용하는 함수입니다. 단, func() 함수는 두 개의 인수를 입력해 첫 번째 인수를 기준으로 그 둘을 비교하고 작으면 음수, 같으면 0, 크면 양수를 반환하는 비교 함수이어야 합니다.

예시

2차원 평면 위의 점 N개를 (x, y) 좌표로 구성한 리스트가 있고 이 리스트를 y 좌표가 증가하는 순으로 정렬하되 y 좌표가 같으면 x좌표가 증가하는 순으로 정렬하를 프로그램입니다.

import functools

def xy_compare(n1: int, n2: int) -> int:
    if n1[1] > n2[1]:           # y좌표가 크면
        return 1
    elif n1[1] == n2[1]:        # y좌표가 같으면
        if n1[0] > n2[0]:       # x좌표가 크면
            return 1
        elif n1[0] == n2[0]:    # x좌표가 같으면
            return 0
        else:                   # x좌표가 작으면
            return -1
    else:
        return 0                # x좌표가 작으면


src = [(0,4), (1, 2), (2, 1), (3, 4), (-1, 2)]
result = sorted(src, key=functools.cmp_to_key(xy_compare))
print(result)   # [(0, 4), (1, 2), (2, 1), (3, 4), (-1, 2)]

xy_compare()와 같이 정렬에 사용하는 함수는 반드시 아래 3가지 중 하나를 반환해야 합니다.

  • 양수
  • 음수
  • 0

functools.partial

functools.partial()은 하나 이상의 인수가 이미 채워진 새 버전의 함수를 만들 때 사용하는 함수입니다.

def add_mul(choice: str, *args: float) -> float:
    if choice == "add":
        result = 0
        for arg in args:
            result = result + arg
    elif choice == "mul":
        result = 1
        for arg in args:
            result = result * arg 
    return result

위의 함수는 입력한 인수의 합과 곱을 choice값에 따라 선택적으로 반환하는 사용자 정의 함수 add_mul()입니다.

만약 add_mul()함수를 활용해 add(), mul() 함수를 만들러면 아래처럼 작성할 수 있습니다.

def add(*args: float) -> float:
    return add_mul("add", *args)

def mul(*args):
    return add_mul("mul", *args)

print(add(1, 2, 3, 4))  # 10
print(mul(1, 2, 3, 4))  # 24

하지만, functools.partial()을 사용하면 아래처럼 더 간결하게 작성할 수 있습니다.

from functools import partial


add = partial(add_mul, "add")
mul = partial(add_mul, "mul")

print(add(1, 2, 3, 4))  # 10
print(mul(1, 2, 3, 4))  # 24
print(type(add))    # <class 'functools.partial'>

이처럼 partial은 하나 이상의 인수를 미리 채운 새로운 함수를 만드는데 유용합니다.

functools.reduce

functools.reduce(function, iterable)은 function을 반복 가능한 객체의 요소에 차례대로(왼쪽에서 오른쪽으로) 누적 적용하여 이 객체를 하나의 값으로 줄이는 함수입니다.

아래는 data의 요소를 모두 더해 반환하는 add()함수입니다.

from typing import Iterable

def add(data: Iterable[int]) -> int:
    result = 0
    for i in data:
        result += i
    return result 

data = [1, 2, 3, 4]
result = add(data)
print(result)   # 10

functools.reduce() 함수를 사용하면 아래처럼 코드를 수정할 수 있습니다.

import functools

data = [1, 2, 3, 4]
result = functools.reduce(lambda x, y: x + y, data)
print(result)   # 10

이렇게 reduce() 함수를 사용하면 reduce()에 선언한 람다 함수를 data 요소에 차례대로 누적 적용하여 다음과 같이 계산합니다.

(((1+2)+3)+4)

참고로 람다 관련 글은 아래 링크를 확인해 보면 됩니다.
람다 관련 글

추가로 functools.reduce()를 활용해 최댓값도 구할 수 있습니다.

num_list = [3, 3, 9, 1, 4]
max_num = functools.reduce(lambda x, y: x if x > y else y, num_list)
print(max_num)  # 9

 

 

'Python > Python' 카테고리의 다른 글

@property 데코레이터  (0) 2023.07.01
glob.glob() 함수  (0) 2023.06.11
Python 라이브러리 - itertools  (0) 2023.05.20
Python 라이브러리 - operator.itemgetter  (0) 2023.05.18
Python 라이브러리 - statistics  (0) 2023.05.17