क्या कोई मुझे यह समझने में सहायता कर सकता है कि acheachedf फ़ंक्शन वापस आने के बाद कैश वैरिएबल अभी भी मौजूद है?
इसे पाइथन के संदर्भ कचरा कलेक्टर की गणना करने के साथ करना है। cache
वैरिएबल संरक्षित और सुलभ होगा क्योंकि फ़ंक्शन _cachedf
का संदर्भ है, और cached
पर कॉलर का संदर्भ है। जब आप फ़ंक्शन को दोबारा कॉल करते हैं, तो आप अभी भी उसी फ़ंक्शन ऑब्जेक्ट का उपयोग कर रहे हैं जो मूल रूप से बनाया गया था, इसलिए आपके पास अभी भी कैश तक पहुंच है।
आप तब तक कैश नहीं खो देंगे जब तक कि इसके सभी संदर्भ नष्ट नहीं हो जाते। ऐसा करने के लिए आप del
ऑपरेटर का उपयोग कर सकते हैं।
उदाहरण के लिए:
>>> import time
>>> def cached(f):
... cache = {} # <---- not an attribute this time!
... def _cachedf(*args):
... if args not in cache:
... cache[args] = f(*args)
... return cache[args]
... return _cachedf
...
...
>>> def foo(duration):
... time.sleep(duration)
... return True
...
...
>>> bob = cached(foo)
>>> bob(2) # Takes two seconds
True
>>> bob(2) # returns instantly
True
>>> del bob # Deletes reference to bob (aka _cachedf) which holds ref to cache
>>> bob = cached(foo)
>>> bob(2) # takes two seconds
True
>>>
रिकॉर्ड के लिए, Memoization क्या आप प्राप्त करने के लिए कोशिश कर रहे हैं कहा जाता है, और वहाँ एक और अधिक पूरा memoizing डेकोरेटर decorator pattern page जो एक ही बात करता है से उपलब्ध है, लेकिन एक का उपयोग कर सजावट वर्ग। आपका कोड और क्लास-आधारित सजावट अनिवार्य रूप से वही है, कक्षा-आधारित सजावटी भंडारण से पहले हैश-क्षमता की जांच कर रहा है।
संपादित करें (2017/02/02): @SiminJie टिप्पणी है कि cached(foo)(2)
हमेशा एक देरी पड़ता है।
ऐसा इसलिए है क्योंकि cached(foo)
ताजा कैश के साथ एक नया फ़ंक्शन देता है। जब cached(foo)(2)
कहा जाता है, तो एक नया ताजा (खाली) कैश बनाया जाता है और फिर कैश किए गए फ़ंक्शन को तुरंत कॉल किया जाता है।
चूंकि कैश खाली है और मूल्य नहीं मिलेगा, यह अंतर्निहित फ़ंक्शन को फिर से चलाता है। इसके बजाय, cached_foo = cached(foo)
करें और फिर cached_foo(2)
कई बार कॉल करें। यह केवल पहली कॉल के लिए देरी होगी। ,
@cached
def my_long_function(arg1, arg2):
return long_operation(arg1,arg2)
my_long_function(1,2) # incurs delay
my_long_function(1,2) # doesn't
आप सज्जाकार के साथ परिचित नहीं हैं तो this answer पर एक नज़र डालें समझने के लिए ऊपर दिए गए कोड का अर्थ है: इसके अलावा, अगर एक डेकोरेटर के रूप में इस्तेमाल, यह उम्मीद के रूप में काम करेंगे।
स्पष्टीकरण के लिए बहुत बहुत धन्यवाद, आपका संपादन चीजों को बहुत स्पष्ट बनाता है। मुझे आश्चर्य है, (सी) पायथन के आंतरिक सीखने के लिए क्या निरीक्षण या कुछ इसी तरह के माध्यम से आपके पिछले पैराग्राफ में "सेल" का उल्लेख करना संभव है? – rahmu
@rahmu: मैंने स्पष्टीकरण में एक त्रुटि को सही किया (जो बहुत अधिक नहीं बदलता है)। दुर्भाग्यवश, कोशिकाएं पाइथन कोड के लिए पूरी तरह से पारदर्शी हैं और हमेशा उस ऑब्जेक्ट द्वारा प्रतिस्थापित की जाती हैं, जिनकी वे संदर्भित करते हैं, इसलिए उनकी जांच नहीं की जा सकती है। –