2

我想创建一个存储数学函数名称、输入(单个数字)和结果的字典。

结构应该类似于cache = {procedure: {input:result}}

i.e.

cache = {'factorial': {4:24, 10:3628800, 20:2432902008176640000},
         'square': {2:4, 5:25, 10:100}
         'sum': {3:6, 5:10, 7:14}}

def factorial(n):
    #print "Running factorial"
    result = 1
    for i in range(2, n + 1):
        result = result * i
    return result

def square(n):
    result = n ^ 2
    return result

def sum(n):
    result = n * 2
    return result

我不希望预先创建缓存字典,因为它可能不知道它将为哪些数学函数存储值。然后我想创建一个名为 cached_execution 的函数,该函数将首先检查缓存是否已为输入调用该函数,如果是,则返回存储为 input:result 对的值的内容。

如果不是,则计算操作,将其存储在缓存中并返回值。如果该函数存在于缓存中,则应在其下创建另一个键/值对。如果没有,则为函数名称创建一个新条目,并将输入/结果的键/值存储在其下。

cached_execution 的结构很简单,但我不知道如何附加到字典。似乎 append 不是字典结构允许的方法。我尝试了各种事情但没有成功。

感谢帮助。

4

5 回答 5

4

您可能还想看看Memoize。有许多可能的实现,其中 3 个在 Python.org wiki 上。即使您编写自己的版本,了解其他人如何解决问题也会很有帮助。

于 2012-07-14T17:27:57.067 回答
1
import pprint

class MathFunctions(object)

    def __init__(self):
        self.cache = {}

    def print_cache(self):
        pprint.pprint(self.cache)

    def factorial(self, n):
        #print "Running factorial"
        result = 1
        for i in range(2, n + 1):
            result = result * i
        return result

    def square(self, n):
        result = n ^ 2
        return result

    def sum(self,n):
        result = n * 2
        return result

    def unknown(self,*args, **kwargs):
        return "UNKNOWN"

if __name__ == "__main__":

    m = MathFunctions()

    functions_to_run = [ 'sum', 'square', 'etc' ]
    input_values     = [ 1, 3.3, 9 ]

    for function in functions_to_run:
        for input in input_values:
            result = m.cache.get(function,{}).get(input,None)

            if None == result:
                if None == m.cache.get(function,None):
                    m.cache[function] = {}
                m.cache[function][input] = getattr(m,function,m.unknown)(input)
于 2012-07-14T17:09:54.487 回答
1

这是一个基于类的方法:

def factorial(x):
    result = 1
    for i in range(2, x+1):
        result *= i
    return result


def square(x):
    return x**2


class CachedMath:
    def __init__(self):
        """create a cached result of function return values so that
        if the same function is called with the same argument more
        than once, the operation is not repeated

        """
        self.cache = {}

    def execute(self, func, number):
        if func not in self.cache:
            #if the function has never been used before
            #create a spot in the cache for it
            self.cache[func] = {}

        if number in self.cache[func]:
            #if this operation has been done before
            #return the cached result
            return self.cache[func][number]
        else:
            #otherwise perform the operation and store the result in cache
            result = func(number)
            self.cache[func][number] = result
            return result

ops = CachedMath()
print ops.execute(factorial, 10)
print ops.execute(factorial, 10)
print ops.execute(square, 9)

只需使用 execute 方法,您就可以为新功能添加新的缓存。

如果您不想使用课程,那么这似乎也对我有用:

def factorial(x):
    result = 1
    for i in range(2, x+1):
        result *= i
    return result

cache = {}
cache[factorial] = {2: 2, 4: 24, 10:362880}
def do_math(func, number):
    if number in cache[func]:
        return cache[func][number]
    else:
        result = func(number)
        cache[func][number] = result
        return result

print do_math(factorial, 10)
print do_math(factorial, 5)
于 2012-07-14T17:32:37.780 回答
0

看一下这个!!!

cache={}

def factorial(n):
    result=1
    for i in range(2, n+1):
        result+=1
    return result

def square(n):
    return n^2

def sum(n):
    return n*2


def cached_execution(function,n):
    if function in cache.keys():    
        if n in cache[function].keys():
            return cache[function][n]
        else:
            if function=='factorial':
                cache['factorial'][n]=factorial(n)
                return cache['factorial'][n] 
            elif function=='square':
                cache['square'][n]=square(n)
                return cache['square'][n]
            elif function=='sum':
                cache['sum'][n]=sum(n)
                return cache['sum'][n]
    else:
        cache[function]={}
        if function=='factorial':
            cache['factorial']={}
            cache['factorial'][n]=factorial(n)
            return cache['factorial'][n] 
        elif function=='square':
            cache['square']={}
            cache['square'][n]=square(n)
            return cache['square'][n]
        elif function=='sum':
            cache['sum']={}
            cache['sum'][n]=sum(n)
            return cache['sum'][n]
        else:
            cache[function]={}      
            cache[function][n]="Define_function"
            return cache[function][n]


cached_execution('sum',8)
cached_execution('square',7)
cached_execution('sum',5)
cached_execution('factorial',10)
cached_execution('log',10)
print cache

它给出的输出为:{'factorial': {10: 10}, 'sum': {8: 16, 5: 10}, 'square': {7: 5}, 'log': {10: 'Define_function'}

于 2012-07-14T17:21:16.043 回答
0

这是您想要做的简单装饰器版本。

def cached_execution(cache):
    def cached_exec_decorator(func):
        def check_cache(x):
            try:
                result = cache[func.__name__][x]
            except KeyError:
                result = func(x)
                if func.__name__ not in cache:
                    cache[func.__name__] = {x : result}
                else:
                    cache[func.__name__][x] = result
            return result
        return check_cache
    return cached_exec_decorator

示例用法:

cache = dict()

# decorator for caching the function call
# you have to pass it a dict to cache in
@cached_execution(cache)
def square(x):
    print "Square is being evaluated!"
    return n ** 2

print square(5) # "Square is being evaluated!\n25" - square(5) isn't cached
print square(5) # "25" - square(5) is cached
print cache # {'square': {5: 25}}

这个方法在语义上比你最初描述的方法和我写这篇文章时发布的其他一些答案要好一些——它隐藏了缓存机制,所以你可以只调用square(x)而不是记住调用cached_execution(square, x)

您也可以将其作为可调用的类装饰器来存储自己的缓存,而不是需要提供对外部缓存字典的引用。我认为这是@Peter Rowell 链接的 memoize 代码片段所使用的方法——直到现在我才知道那个页面或名称。

于 2012-07-14T17:49:36.367 回答