Memoizing decorator keeping stored values

孤者浪人 提交于 2021-02-07 04:21:05

问题


I have a memoization decorator that looks like this:

def memoize(obj):
    from functools import wraps
    cache = {}

    @wraps(obj)
    def memoizer(*args, **kwargs):
        if args not in cache:
            cache[args] = obj(*args, **kwargs)
        return cache[args]

    return memoizer

However, I'm not sure this function works properly because it seems like to me it recreates cache as an empty dictionary every time the decorated function is called. When I test it with a simple fibonacci function, it does appear to memoize correctly. So is cache not recreated every time?

The python wiki has a version that includes this line:

cache = obj.cache = {}

So I am not sure what this does. I guess that python functions are objects so it is creating a new attribute associated with the function and is publically available/usable every time the function is called.

In either version, if I make repeated calls to the function, as in a recursive definition or just through repeated calls, how is the cache treated? Is it associated with the function, does it become a "global" variable, or something else?


回答1:


1) A new cache is created for each call to memoize(). But memoize() is called only once for each decorated function. Thus each decorated function has its own cache.

2) Concerning cache = obj.cache = {}:

Functions are also objects in Python. And as you already assumed, obj.cache = {} will create a new attribute on the wrapped function. The local cache object and the cache attribute on the wrapped function will point at the same dictionary.

This does not man that cache is a global variable - it's local in the memoize function and it's a attribute on the function.

If you have a decorated function f you could access f.cache on a global scope, if that's what you mean with a global variable.

If you call the decorated function repeatedly, it will always access the same cache specific to the decorated function.


To work around inner functions not beeing "memoized".

def outer():
    # do not add the decorator here!
    def inner():
        return 5
    if(not hasattr(outer, "inner")):
        # the "@" decorator is only syntactical sugar, 
        # we can simply call the decorator function to wrap another function
        outer.inner = memoize( inner )
    outer.inner()
    return outer.inner()

outer()
outer()


来源:https://stackoverflow.com/questions/44577679/memoizing-decorator-keeping-stored-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!