繁体   English   中英

Memoization装饰器

[英]Memoization Decorator

我有以下伪代码:

class myClass()
  def slow_method(self):
     try:
         return self.memo_slow_method
     except:
         self.memo_slow_method = some_slow_function()
         return self.memo_slow_method

是否有可能构建一个完全执行此逻辑的memoization装饰器?

限制:

  • 虽然memo_slow_method不需要直接访问,但必须在对象上定义,以便在清除对象本身时清除它 - 非常重要
  • 没有必要考虑除self参数 - 不会传递任何参数。

PS我一直在使用@lrucache,但它不适合我的目的。 它确实需要完全遵循上述逻辑。

您可以使用描述符(类似属性)而不是装饰器:

class Memoize(object):
    def __init__(self, name, func):
        self.name = name  # name of the memo attribute
        self.func = func  # the function that is executed when there is no memo

    def __get__(self, obj, typ=None):
        if obj:
            try:
                return getattr(obj, self.name)
            except:
                setattr(obj, self.name, self.func())
                return getattr(obj, self.name)
        else:
            return self

然后设置描述符:

class Fun(object):
    meth = Memoize('x', lambda: print('in') or 10)

然后是互动测试:

>>> f = Fun()
>>> f.meth  # function is executed
'in'
10
>>> f.x
10
>>> f.meth  # function is not executed
10

如果你真的想要一个装饰者:

def memoize(func):
    def inner(self):
        try:
            return self.memo_slow_method   # hardcoded memo attribute name
        except:
            self.memo_slow_method = func(self)  # execute the method body
            return self.memo_slow_method
    return inner

class Fun(object):
    @memoize
    def meth(self):
        print('in')
        return 100

>>> f = Fun()
>>> f.meth()
'in'
100
>>> f.meth()
100
>>> f.memo_slow_method
100

这是一个装饰器,可以根据要求准确地实现您的逻辑。 它通过向函数名称添加前缀来从函数名称(在func.__name__可用)中为备注字段的名称func.__name__

from __future__ import print_function
import time
from functools import wraps

memo_prefix = '_memo_' # Check for possible name collision

def deco(func):
    memo_field_name = memo_prefix + func.__name__

    def ret_func(self):
        try:
            return getattr(self, memo_field_name)
        except AttributeError:
            ret_val = func(self)
            setattr(self, memo_field_name, ret_val)
            return ret_val
    return ret_func

def some_slow_function():
    for x in range(3):
        time.sleep(1)
        print('Waiting...', x)
    return 'Done'

class myClass():
    @deco
    def slow_method(self):
        return some_slow_function()

现在测试一下:

In [2]: it = myClass()

In [3]: print(it.slow_method())
Waiting... 0
Waiting... 1
Waiting... 2
Done

In [4]: print(it.slow_method())
Done

In [5]: print(it.__dict__)
{'_memo_slow_method': 'Done'}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM