记忆装饰器保持存储的值 [英] Memoizing decorator keeping stored values

查看:60
本文介绍了记忆装饰器保持存储的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的备忘录装饰器:

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

但是,我不确定这个函数是否正常工作,因为在我看来,每次调用装饰函数时,它都会将 cache 重新创建为一个空字典.当我用一个简单的斐波那契函数测试它时,它似乎确实能正确记忆.那么cache不是每次都重新创建吗?

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?

python wiki 有一个版本,其中包括这一行:

cache = obj.cache = {}

所以我不确定这是做什么的.我猜python函数是对象,因此它正在创建一个与函数关联的新属性,并且每次调用函数时都是公开可用/可用的.

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) 为每次调用 memoize() 创建一个新的 cache.但是 memoize() 对于每个装饰函数只调用一次.因此,每个修饰函数都有自己的cache.

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) 关于cache = obj.cache = {}:

函数在 Python 中也是对象.正如您已经假设的那样, 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.

这并不认为 cache 是一个全局变量——它在 memoize 函数中是局部的,并且是函数的一个属性.

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.

如果你有一个修饰函数 f,你可以在全局范围内访问 f.cache,如果这就是你对全局变量的意思.

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.

如果重复调用装饰函数,它将始终访问特定于装饰函数的相同cache.

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()

这篇关于记忆装饰器保持存储的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆