2017-03-03 76 views
3

我有以下的伪代码:记忆化装饰

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,但它不适合我的目的。它确实需要严格遵循上述逻辑。

+0

会有什么some_slow_function回来吗?方法还是值?请问slow_method函数返回吗? –

+0

有一个[memoization修饰器的配方](https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize)。由于Python 3.2,[类似](https://docs.python.org/3/library/functools.html#functools.lru_cache)包含在标准库中。 – mkrieger1

回答

2

相反,你可以使用一个描述符(财产等),一个装饰的:

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 
0

这是一个装饰器,可按要求准确地实现您的逻辑。 它硬币从函数名(这是提供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'}