How do I store the results of a calculation in Python so that my program doesn't calculate the same thing twice?

I'm having trouble with Python programs (I'm a complete newb) where it doesn't store data from calculations and does it over and over again when it feels like it should have saved it. How can I get Python to save the answer so that it doesn't calculate the program over and over?

Example:

import prime
def g(x):
    i=0
    while i<len(prime.sieve(x)):
        print str(prime.sieve(x)[i])+' is prime'
        i=i+1

      

Here's the "prime" module in case anyone wants to compile this:

def sieve(max):
    #Takes in a number, and returns all primes between 2 and that number

    #Start with all of the numbers
    primes = range(2,max+1)
    #Start running through each number 
    for i in primes:
            #Start with double the number, and
            j = 2
            #remove all multiples
            while i * j <= primes[-1]:
                    #As long as the current multiple of the number
                    #is less than than the last element in the list
                    #If the multiple is in the list, take it out
                    if i * j in primes:
                            primes.remove(i*j)
                    j=j+1
    return primes

      

Anyway, the first bit of code is calculating the "prime.sieve (x)" list over and over again, and I want to keep it for reference when printing. In the meantime, there is no need to know about it. ”

Thank!

rofls

+3


source to share


4 answers


saved_sieve_map = {}
def saved_sieve(x):
  if x not in saved_sieve_map:
    saved_sieve_map[x] = sieve(x)
  return saved_sieve_map[x]

      



+4


source


This is called memoization. Fortunately, there are many memory decorators and one of them is located here: http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize

Usage example:



@memoized
def fibonacci(n):
   "Return the nth fibonacci number."
   if n in (0, 1):
      return n
   return fibonacci(n-1) + fibonacci(n-2)

print fibonacci(12)

      

(the expression @memoized

applies the decorator to the function following it).

+4


source


You can simply assign it to a local variable:

i=0
saveit = prime.sieve(x)
while i<len(saveit):
    print str(saveit[i])+' is prime'
    i=i+1

      

Note: it still computes the sieve even if g(x)

called twice with the same value x

. For a version that keeps the calculation even outside the scope g

, see Keith's answer for example.

0


source


This function can be used to eliminate recursive complexity.

from functools import wraps
def memo(func): 
    cache = {}
    @wraps(func)
    def wrap(*args):
        if args not in cache: 
            cache[args] = func(*args)
        return cache[args] 
    return wrap

      

Anyway, this is my implementation of a sieve that should be faster than yours.

@memo
def sieve(end):
    import itertools
    lng = ((end/2)-1+end%2)
    sieve = [True]*(lng+1)
    for i in itertools.ifilter(lambda z: sieve[z],xrange(int(end**0.5) >> 1)):
        n=len(sieve[int((i*(i + 3) << 1) + 3): int(lng): int((i << 1) + 3)])
        sieve[int((i*(i + 3) << 1) + 3): int(lng): int((i << 1) + 3)]=[False]*n
    return sum([(x << 1) + 3 for x in itertools.compress(xrange(lng),sieve)])+2

      

0


source







All Articles