Tôi đang cố gắng xây dựng một trình trang trí cho một phương thức thể hiện của một lớp sẽ ghi nhớ kết quả. (Điều này đã được thực hiện một triệu lần trước) Tuy nhiên, tôi muốn tùy chọn có thể đặt lại bộ nhớ cache đã ghi nhớ tại bất kỳ thời điểm nào (ví dụ, nếu một cái gì đó trong trạng thái cá thể thay đổi, điều này có thể thay đổi kết quả của phương thức không có gì để làm với args của nó). Vì vậy, tôi đã cố gắng xây dựng một trình trang trí như một lớp thay vì một hàm, để tôi có thể có quyền truy cập vào bộ nhớ cache với tư cách là một thành viên của lớp. Điều này dẫn tôi xuống con đường học hỏi về các mô tả, cụ thể là phương pháp __get__
, đó là nơi tôi thực sự bị mắc kẹt. Mã của tôi trông giống như vậy:python resizable instance method memoization decorator
import time
class memoized(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args, **kwargs):
key = (self.func, args, frozenset(kwargs.iteritems()))
try:
return self.cache[key]
except KeyError:
self.cache[key] = self.func(*args, **kwargs)
return self.cache[key]
except TypeError:
# uncacheable, so just return calculated value without caching
return self.func(*args, **kwargs)
# self == instance of memoized
# obj == instance of my_class
# objtype == class object of __main__.my_class
def __get__(self, obj, objtype=None):
"""Support instance methods"""
if obj is None:
return self
# new_func is the bound method my_func of my_class instance
new_func = self.func.__get__(obj, objtype)
# instantiates a brand new class...this is not helping us, because it's a
# new class each time, which starts with a fresh cache
return self.__class__(new_func)
# new method that will allow me to reset the memoized cache
def reset(self):
print "IN RESET"
self.cache = {}
class my_class:
@memoized
def my_func(self, val):
print "in my_func"
time.sleep(2)
return val
c = my_class()
print "should take time"
print c.my_func(55)
print
print "should be instant"
print c.my_func(55)
print
c.my_func.reset()
print "should take time"
print c.my_func(55)
Điều này rõ ràng và/hoặc có thể? Mỗi khi __get__
được gọi, tôi nhận được một phiên bản hoàn toàn mới của lớp được ghi nhớ, làm mất bộ nhớ cache với dữ liệu thực tế trong đó. Tôi đã làm việc chăm chỉ với __get__
, nhưng không đạt được nhiều tiến bộ.
Có cách tiếp cận hoàn toàn riêng biệt nào cho vấn đề này mà tôi đang thiếu hoàn toàn không? Và tất cả các lời khuyên/đề xuất đều được chào đón và đánh giá cao. Cảm ơn.
tôi đã không đi sâu hơn trong mã của bạn, nhưng đối với hiệu suất tốt hơn bạn nên sử dụng 'nếu bộ nhớ cache .has_key (...): return cache [...] 'thay vì bắt' KeyError'. – khachik
@khachik: 'khóa trong bộ nhớ cache' tốt hơn, vì' has_key' không được dùng nữa. – delnan
Hãy nhớ rằng điểm ghi nhớ là một cuộc gọi hàm với cùng các đối số tạo ra cùng một đầu ra. Nếu bạn thực sự cần phải thiết lập lại bộ nhớ đệm dựa trên trạng thái cá thể, có lẽ bạn nên xem xét việc giữ bộ nhớ cache trong cá thể thay vì một trình trang trí được ghi nhớ. – Falmarri