我有以下伪代码:
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装饰器?
限制:
self
以外的参数 - 不会传递任何参数。PS我一直在使用@lrucache,但它不适合我的目的。它确实需要完全遵循上述逻辑。
答案 0 :(得分: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
答案 1 :(得分: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'}