DEV/Python

Python Decorator with Memoization

young.gratia 2021. 7. 13. 09:45

자바스크립트에서도 많이 예시로 드는 코드인데, Python에서는 Decorator를 사용하여 아래와 같이 cache attribute를 추가한 후, 이미 계산된 값이면 바로 돌려주고 아니면 계산을 해서 값을 저장하는 단계를 추가로 거치도록 하여 memoization 할 수 있다.

import functools
from decorators import count_calls

def cache(func):
    """Keep a cache of previous function calls"""
    @functools.wraps(func)
    def wrapper_cache(*args, **kwargs):
        cache_key = args + tuple(kwargs.items())
        if cache_key not in wrapper_cache.cache:
            wrapper_cache.cache[cache_key] = func(*args, **kwargs)
        return wrapper_cache.cache[cache_key]
    wrapper_cache.cache = dict()
    return wrapper_cache

@cache
@count_calls
def fibonacci(num):
    if num < 2:
        return num
    return fibonacci(num - 1) + fibonacci(num - 2)

https://realpython.com/primer-on-python-decorators/

 

Primer on Python Decorators – Real Python

In this introductory tutorial, we'll look at what Python decorators are and how to create and use them.

realpython.com

아래와 같이 이미 표준 라이브러리에서 cache도 제공한다.

Decorator to wrap a function with a memoizing callable that saves up to the maxsize most recent calls. It can save time when an expensive or I/O bound function is periodically called with the same arguments.
Since a dictionary is used to cache results, the positional and keyword arguments to the function must be hashable.

https://docs.python.org/3/library/functools.html#functools.lru_cache

 

functools — Higher-order functions and operations on callable objects — Python 3.9.6 documentation

 

docs.python.org