2013-02-18 21 views
23

LRU कैश डेकोरेटर का उपयोग करते हुए पाया गया: http://code.activestate.com/recipes/578078-py26-and-py30-backport-of-python-33s-lru-cache/अजगर LRU कैश डेकोरेटर प्रति उदाहरण

from lru_cache import lru_cache 
class Test: 
    @lru_cache(maxsize=16) 
    def cached_method(self, x): 
     return x + 5 

मैं इस के साथ एक सजाया वर्ग विधि बना सकते हैं, लेकिन यह एक वैश्विक कैश सभी उदाहरणों पर लागू होने वाला बनाने समाप्त होता है कक्षा परीक्षण के। हालांकि, मेरा इरादा प्रति उदाहरण कैश बनाना था। तो अगर मैं 3 टेस्ट को चालू करना चाहता था, तो मेरे पास 3 एलआरयू कैश के बजाय 3 एलआरयू कैश होंगे जो सभी 3 उदाहरणों के लिए होगा।

एकमात्र संकेत यह है कि यह हो रहा है कि यह हो रहा है कि विभिन्न वर्ग उदाहरणों पर cache_info() को सजाए गए तरीकों पर कॉल करते समय, वे सभी एक ही कैश आंकड़े वापस लौटाते हैं (जो होने की संभावना नहीं है क्योंकि उन्हें बहुत अलग तरीके से बातचीत की जा रही है तर्क):

CacheInfo(hits=8379, misses=759, maxsize=128, currsize=128) 
CacheInfo(hits=8379, misses=759, maxsize=128, currsize=128) 
CacheInfo(hits=8379, misses=759, maxsize=128, currsize=128) 

वहाँ एक डेकोरेटर या चाल है कि मुझे आसानी से प्रत्येक वर्ग के उदाहरण के लिए एक कैश बनाने के लिए इस डेकोरेटर का कारण करने की अनुमति होगी है?

+1

याद रखें, एक सजावटी 'डीफ विधि के लिए सिंटैक्स चीनी है: पास; विधि = सजाने (विधि) '। तो आप अपने '__init__' में सजाए गए विधि को बनाने के लिए यांत्रिक रूप से इसका अनुवाद कर सकते हैं। –

+0

क्या आप वाकई जानते हैं कि आप जानते हैं कि "क्लास विधि" क्या है? क्योंकि मुझे लगता है कि आप एक सामान्य विधि की तलाश में हैं। यदि एक वर्ग विधि उदाहरण विशिष्ट है, तो परिभाषा के अनुसार, एक उदाहरण की एक सामान्य विधि है। या आपको वास्तव में कक्षा विधि की आवश्यकता क्यों है? या आप "प्रति-उदाहरण" कैश क्यों चाहते हैं? – Mayou36

उत्तर

28

, मान लें कि आप कोड (जैसे संशोधित करने के लिए नहीं करना चाहते हैं, क्योंकि आप अपने कोड में एक नुस्खा चिपकाने functools32 नकल के बजाय PyPI से बाहर का उपयोग stdlib functools.lru_cache का उपयोग सिर्फ 3.3 करने के लिए बंदरगाह करने में सक्षम हो सकता है और, या और करना चाहते हैं), एक स्पष्ट समाधान है: प्रत्येक उदाहरण के साथ एक नई सजाया उदाहरण विधि बनाएँ।

class Test: 
    def cached_method(self, x): 
     return x + 5 
    def __init__(self): 
     self.cached_method = lru_cache(maxsize=16)(self.cached_method) 
+1

बहुत बढ़िया। लेकिन मैं केवल एक ही @property के लिए यह कैसे कर सकता हूं? – Gilly

2

कैसे इस बारे में: एक समारोह डेकोरेटर कि विधि lru_cache पहली बार यह प्रत्येक उदाहरण पर कहा जाता है के साथ लपेटता? कुछ इनलाइन प्रलेखन के साथ

class Foo: 
    @instance_method_lru_cache() 
    def times_2(self, bar): 
     return bar * 2 

foo1 = Foo() 
foo2 = Foo() 

print(foo1.times_2(2)) 
# creating cache 
# 4 
foo1.times_2(2) 
# 4 

print(foo2.times_2(2)) 
# creating cache 
# 4 
foo2.times_2(2) 
# 4 

Here's a gist on GitHub:

def instance_method_lru_cache(*cache_args, **cache_kwargs): 
    def cache_decorator(func): 
     @wraps(func) 
     def cache_factory(self, *args, **kwargs): 
      print('creating cache') 
      instance_cache = lru_cache(*cache_args, **cache_kwargs)(func) 
      instance_cache = instance_cache.__get__(self, self.__class__) 
      setattr(self, func.__name__, instance_cache) 
      return instance_cache(*args, **kwargs) 
     return cache_factory 
    return cache_decorator 

इस तरह यह प्रयोग करें।

संबंधित मुद्दे