코드 재사용 및 최적화를 위해 사용하는 functools 주요 기능 6가지
functools는 파이썬의 표준 라이브러리 모듈로, 고차 함수(higher-order functions)와 관련된 여러 가지 유용한 함수들을 제공합니다. 처음 도입은 파이썬 2.5였습니다. 이 functools 모듈은 함수형 프로그래밍 패러다임을 지원하기 위해 개발되었기때문에 코드의 재사용성과 가독성을 높입니다. 함수형 프로그래밍은 함수를 일급 객체로 취급하며, 함수의 조합과 변형을 통한 코딩을 지향합니다. 주요 특징은 3가지 입니다.
- 재사용성: 자주 사용하는 패턴이나 기능을 함수로 묶어 재사용할 수 있도록 합니다.
- 가독성: 코드의 가독성을 높이고, 중복 코드를 줄여줍니다.
- 성능 최적화: 특정 함수의 실행을 캐싱하거나, 다른 방법으로 최적화할 수 있는 기능을 제공합니다.
그리고 functools 모듈은 다음과 같은 상황에서 유용합니다:
- 반복적인 인수 고정: 동일한 인수를 반복적으로 사용해야 할 때 partial을 사용하여 함수 호출을 단순화합니다.
- 성능 최적화: 계산이 오래 걸리는 함수의 결과를 캐싱하여 성능을 높이고 싶을 때 lru_cache를 사용합니다.
- 누적 계산: 리스트 등의 iterable 객체에 대해 누적 계산을 수행할 때 reduce를 사용합니다.
- 데코레이터 작성: 함수의 메타데이터를 유지하면서 데코레이터를 작성할 때 wraps를 사용합니다.
functools의 주요 기능
1) partial
partial 함수는 어떤 함수의 인수를 고정하여 새로운 함수를 생성합니다. 이를 통해 매번 동일한 인수를 반복해서 입력할 필요 없이 함수 호출을 단순화할 수 있습니다.
from functools import partial
def multiply(x, y):
return x * y
# y 값을 2로 고정한 새로운 함수 생성
double = partial(multiply, y=2)
print(double(5)) # 출력: 10
2) lru_cache
lru_cache는 Least Recently Used (LRU) 캐싱을 구현한 데코레이터로, 동일한 입력값에 대해 계산된 결과를 캐시하여 함수의 실행 속도를 높일 수 있습니다.
from functools import lru_cache
import time
@lru_cache(maxsize=None)
def slow_function(n):
time.sleep(2) # 계산이 오래 걸리는 함수 시뮬레이션
return n * n
start = time.time()
print(slow_function(4)) # 처음 호출, 2초 지연
print("Elapsed time:", time.time() - start)
start = time.time()
print(slow_function(4)) # 캐시된 결과 사용, 지연 없음
print("Elapsed time:", time.time() - start)
3) cmp_to_key
cmp_to_key는 Python 2 스타일의 비교 함수를 Python 3 스타일의 키 함수로 변환하는 데 사용됩니다. Python 3에서는 비교 함수 대신 키 함수를 사용하여 정렬을 수행합니다. 아래는 문자열 리스트를 길이에 따라 정렬하는 예제입니다.
from functools import cmp_to_key
# Python 2 스타일 비교 함수
def compare_len(str1, str2):
if len(str1) < len(str2):
return -1
elif len(str1) > len(str2):
return 1
else:
return 0
# 비교 함수를 키 함수로 변환
key_func = cmp_to_key(compare_len)
# 정렬할 문자열 리스트
words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape"]
# 키 함수를 사용하여 정렬
sorted_words = sorted(words, key=key_func)
print("Sorted words by length:", sorted_words)
4) reduce
reduce 함수는 함수와 iterable을 인수로 받아, iterable의 요소들을 누적적으로 함수에 적용하여 단일 결과를 반환합니다. Python 3부터는 내장 함수에서 functools 모듈로 이동되었습니다
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# 누적 합계 계산
total = reduce(lambda x, y: x + y, numbers)
print(total) # 출력: 15
5) total_ordering
total_ordering은 클래스에 비교 연산자 메소드를 최소한으로 구현하여 나머지 비교 연산자를 자동으로 추가해주는 데코레이터입니다. 이를 통해 코드의 중복을 줄이고 클래스 정의를 간결하게 만들 수 있습니다. 아래는 total_ordering을 사용하여 클래스에 비교 연산자를 구현하는 예제입니다.
from functools import total_ordering
@total_ordering
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
if isinstance(other, Person):
return self.age == other.age
return NotImplemented
def __lt__(self, other):
if isinstance(other, Person):
return self.age < other.age
return NotImplemented
def __repr__(self):
return f"Person(name={self.name}, age={self.age})"
# Person 객체 생성
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)
person3 = Person("Charlie", 30)
# 비교 연산자 사용
print(person1 == person2) # 출력: False
print(person1 == person3) # 출력: True
print(person1 < person2) # 출력: False
print(person2 < person1) # 출력: True
print(person1 > person2) # 출력: True
# 정렬 예제
people = [person1, person2, person3]
sorted_people = sorted(people)
print(sorted_people) # 출력: [Person(name=Bob, age=25), Person(name=Alice, age=30), Person(name=Charlie, age=30)]
6) wraps
wraps 데코레이터는 데코레이터를 만들 때, 원래 함수의 메타데이터(이름, 문서 문자열 등)를 유지하기 위해 사용됩니다. 이는 디버깅과 문서화에 매우 유용합니다.
from functools import wraps
def my_decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = f(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello(name):
"""Prints a greeting."""
print(f"Hello, {name}!")
say_hello("Alice")
print(say_hello.__name__) # 출력: say_hello
print(say_hello.__doc__) # 출력: Prints a greeting.
'코딩취미 > Python' 카테고리의 다른 글
QLineEdit 안에 Button 넣는 방법 : QToolButton or QAction 사용 (0) | 2024.06.11 |
---|---|
파이썬 예외처리(try, except, else, finally) 방법 과 사용자 정의 예외 처리 객체 사용 (0) | 2024.06.01 |
partial 사용 방법과 이벤트 핸들러 적용 시 장점 (0) | 2024.05.30 |
딕셔너리 값을 보기 좋게 출력하는 방법 (pprint, json) (0) | 2024.05.27 |
QGraphicsLineItem, QGraphicsTextItem 인터렉티브 강화 코드 (mouse over/hover/click event 처리) (0) | 2024.05.03 |