2010-07-31 22 views
10

यह "अच्छा अभ्यास" है कि नीचे एक आप के लिए Memoization प्रक्रिया संभाल कर सकते हैं की तरह एक वर्ग बनाने के लिए है? Memoization के लाभों को इतना महान है कि ऐसा लगता है इस तरह एक वर्ग उपयोगी होगा (यह एक है, जहां यह 501,003 ने 1507 से समारोह कॉल करने के लिए और अपने कंप्यूटर पर CPU समय का 1.409 0.006 सेकंड से चला जाता है की तरह है, कुछ मामलों में) कर रहे हैं।Memoization हैंडलर

हालांकि, मैं eval() के उपयोग पर केवल नकारात्मक टिप्पणी पढ़ा है। क्या यह उपयोग इस पहुंच के लचीलेपन के कारण, यह उपयोग करने योग्य है?

इस दुष्प्रभाव को खोने की कीमत पर स्वचालित रूप से किसी भी दिए गए मान बचा सकता है। धन्यवाद।

import cProfile 

class Memoizer(object): 
    """A handler for saving function results.""" 
    def __init__(self): 
     self.memos = dict() 
    def memo(self, string): 
     if string in self.memos: 
      return self.memos[string] 
     else: 
      self.memos[string] = eval(string) 
      self.memo(string) 

def factorial(n): 
    assert type(n) == int 
    if n == 1: 
     return 1 
    else: 
     return n * factorial(n-1) 

# find the factorial of num 
num = 500 
# this many times 
times = 1000 

def factorialTwice(): 
    factorial(num) 
    for x in xrange(0, times): 
     factorial(num) 
    return factorial(num) 

def memoizedFactorial(): 
    handler = Memoizer() 
    for x in xrange(0, times): 
     handler.memo("factorial(%d)" % num) 
    return handler.memo("factorial(%d)" % num) 


cProfile.run('factorialTwice()') 

cProfile.run('memoizedFactorial()') 
+0

आप के बारे में "अजगर सज्जाकार" और Memoization बात कर रहे हैं उनके लिए एक शानदार इस्तेमाल होता है। और इसके लिए evals की आवश्यकता नहीं है (जो आंशिक रूप से बुराई है; आप सही ढंग से सुना है)। – msw

उत्तर

13

आप eval का सहारा के बिना memoize कर सकते हैं।

एक (बहुत बुनियादी) memoizer:

def memoized(f): 
    cache={} 
    def ret(*args): 
     if args in cache: 
      return cache[args] 
     else: 
      answer=f(*args) 
      cache[args]=answer 
      return answer 
    return ret 

@memoized 
def fibonacci(n): 
    if n==0 or n==1: 
     return 1 
    else: 
     return fibonacci(n-1)+fibonacci(n-2) 

print fibonacci(100) 
5

eval अक्सर evil के रूप में misspelt है इसका मुख्य कारण रनटाइम पर "तार" को क्रियान्वित करने के विचार सुरक्षा विचारों से भरा है। क्या आप पर्याप्त रूप से कोड से बच गए हैं? उद्धरण चिह्न? और कई परेशान सिरदर्द। आपका ज्ञापन हैंडलर काम करता है लेकिन यह वास्तव में चीजों को करने का पाइथन तरीका नहीं है। एमएके का दृष्टिकोण बहुत अधिक पाइथोनिक है। आइए कुछ प्रयोगों को आज़माएं।

मैं दोनों संस्करणों को संपादित किया है और उन्हें सिर्फ 100 इनपुट के रूप में के साथ एक बार चलाने बना दिया। मैंने Memoizer के तत्कालता को भी बाहर कर दिया। यहां परिणाम हैं।

>>> timeit.timeit(memoizedFactorial,number=1000) 
0.08526921272277832h 
>>> timeit.timeit(foo0.mfactorial,number=1000) 
0.000804901123046875 

इस के अलावा, अपने संस्करण है जो एक तार में लिखा जाना चाहिए समारोह memoised जा करने के लिए चारों ओर एक आवरण आवश्यकता होती है। वह बदसूरत है। एमएके का समाधान साफ ​​है क्योंकि "ज्ञापन की प्रक्रिया" एक अलग समारोह में encapsulated है जिसे आसानी से किसी भी महंगी समारोह में किसी भी महंगी समारोह में लागू किया जा सकता है। यह बहुत पाइथनिक नहीं है। मेरे रुचि रखने पर http://nibrahim.net.in/self-defence/ पर मेरे पायथन ट्यूटोरियल में ऐसे सजावट लिखने पर मेरे पास कुछ विवरण हैं।

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