Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类成员函数的Memoize包装器以返回部分值_Python_Wrapper_Memoization_Functools - Fatal编程技术网

Python 类成员函数的Memoize包装器以返回部分值

Python 类成员函数的Memoize包装器以返回部分值,python,wrapper,memoization,functools,Python,Wrapper,Memoization,Functools,我使用的是来自的memoize配方,并对其进行了轻微修改,使其用于返回2个值的函数。我使用这个包装器创建两个单独的函数,分别返回第一个值和第二个值,但是函数求值是缓存的,这样当使用相同的参数调用任何一个返回的函数时就不会有开销。下面是这个包装器的代码 def memoize(obj, cache_limit=10): ''' This function caches the return value each time it is called. partial() is use

我使用的是来自的memoize配方,并对其进行了轻微修改,使其用于返回2个值的函数。我使用这个包装器创建两个单独的函数,分别返回第一个值和第二个值,但是函数求值是缓存的,这样当使用相同的参数调用任何一个返回的函数时就不会有开销。下面是这个包装器的代码

def memoize(obj, cache_limit=10):
    '''
    This function caches the return value each time it is called. partial() is used to return the appropriate value.
    Cache size is limited to 10
    See here for details on this design pattern: https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
    '''
    cache = obj.cache = {}
    key_cache = collections.deque()

    @functools.wraps(obj)
    def memoizer(which, *args, **kwargs):
        key = str(args)
        if key not in cache:
            cache[key] = obj(*args, **kwargs)
            key_cache.append(key)
            if len(key_cache) >= cache_limit:
                del cache[key_cache.popleft()]
        return cache[key][which]
    return functools.partial(memoizer, 0), functools.partial(memoizer, 1)
现在,我尝试在函数
f
上使用它,该函数在类中的定义如下:

class test_function:
    def __init__(self):
        ''''''

    def f(self,x):
        return 2*x, 3*x
我这样称呼它

a = test_function()
f_v1, f_v2 = memoize(a.f)
如果成功
f_v1(x)
将返回
2x
f_v2(x)
将返回
3x
。但这失败了,出现了一个错误:

AttributeError: 'instancemethod' object has no attribute 'cache'

如果函数在类之外声明,我的代码可以正常工作。我错过了什么?我使用的是
Python2.7

方法是一种与函数不同的对象(如错误消息所示,是一种
instancemethod
对象;这种类型可用作
types.MethodType
)。与函数对象不同,实例方法没有
\uuuu dict\uuu
,因此不能对其设置任意属性;您不能通过
obj.someMethod.someAttribute=“blah”
在方法上创建自己的名为
someAttribute
的自定义属性

我不清楚为什么要将缓存存储在对象上,因为实际上从未从那里访问它。如果只使用局部变量
缓存
,它将保存在闭包中,并且可以正常工作:

def memoize(obj, cache_limit=10):
    '''
    This function caches the return value each time it is called. partial() is used to return the appropriate value.
    Cache size is limited to 10
    See here for details on this design pattern: https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
    '''
    cache = {}
    key_cache = collections.deque()

    @functools.wraps(obj)
    def memoizer(which, *args, **kwargs):
        key = str(args)
        if key not in cache:
            cache[key] = obj(*args, **kwargs)
            key_cache.append(key)
            if len(key_cache) >= cache_limit:
                del cache[key_cache.popleft()]
        return cache[key][which]
    return functools.partial(memoizer, 0), functools.partial(memoizer, 1)

>>> a = test_function()
... f_v1, f_v2 = memoize(a.f)
>>> f_v1(2)
4
>>> f_v2(2)
6

我懂了。。。假设我有一个函数
f2()
,我想用这个包装器来记忆它,
缓存
会不会与
f()
中的
缓存
冲突?我检查了它,它工作正常,但是您能解释一下
缓存的范围吗?@RazorXsr:由于
缓存
是一个局部变量,因此每次调用
memoize
时都会创建一个新的变量。这个网站上有很多关于闭包的问题(比如)。谷歌搜索“Python闭包”可以找到很多关于Python闭包的信息。