我已經有一個記錄器,工作得很好。它使用pickle轉儲序列化輸入並創建MD5散列作爲鍵。函數結果非常大,並且存儲爲文件名爲MD5哈希的pickle文件。當我連續調用兩個memoized函數時,memoizer
將加載第一個函數的輸出並將其傳遞給第二個函數。第二個函數將序列化它,創建MD5然後加載輸出。這裏是一個非常簡單的代碼:python中的鏈式記憶器
@memoize
def f(x):
...
return y
@memoize
def g(x):
...
return y
y1 = f(x1)
y2 = g(y1)
y1
從磁盤加載時f
進行評估,然後當g
評估它的序列化。是否有可能繞過這一步並將y1
(即MD5哈希)的密鑰傳遞給g
?如果g
已經有此密鑰,它將從磁盤加載y2
。如果不是,則「請求」完整y1
以評估g
。
編輯:
import cPickle as pickle
import inspect
import hashlib
class memoize(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
arg = inspect.getargspec(self.func).args
file_name = self._get_key(*args, **kwargs)
try:
f = open(file_name, "r")
out = pickle.load(f)
f.close()
except:
out = self.func(*args, **kwargs)
f = open(file_name, "wb")
pickle.dump(out, f, 2)
f.close()
return out
def _arg_hash(self, *args, **kwargs):
_str = pickle.dumps(args, 2) + pickle.dumps(kwargs, 2)
return hashlib.md5(_str).hexdigest()
def _src_hash(self):
_src = inspect.getsource(self.func)
return hashlib.md5(_src).hexdigest()
def _get_key(self, *args, **kwargs):
arg = self._arg_hash(*args, **kwargs)
src = self._src_hash()
return src + '_' + arg + '.pkl'
爲什麼不爲你的兩個函數使用一個命名空間?我的意思是你應該使用一個基於鍵值的文件(如json等)。 – Kasramvd
目前的方法究竟是什麼問題?是否(幾乎)同一大塊數據在光盤上保存兩次?如果其中一個功能只是做「便宜」的東西,不要「@記憶」它;否則,我認爲沒有一個好辦法解決這個問題。 –
@MSeifert這是一個非常簡單的例子,我有一組使用一個輸出作爲另一個輸入的函數。所以將其轉換爲'g(f(x))'並不總是很容易。 – mss