python:添加/附加动态键:动态字典中的值对

时间:2012-07-14 16:56:03

标签: python dynamic dictionary append key

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

结构应该类似于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不是字典结构允许的方法。我尝试了各种各样的事情但没有成功。

感谢帮助。

5 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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)

答案 2 :(得分: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)

答案 3 :(得分: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'}

答案 4 :(得分: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)

你可能也可以将它作为一个可调用的类装饰器来存储它自己的缓存,而不是需要提供对外部缓存dict的引用。我认为这是@Peter Rowell链接的memoize代码片段使用的方法 - 我到目前为止还不知道该页面或名称。