Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python内存化手动缓存_Python_Memoization - Fatal编程技术网

Python内存化手动缓存

Python内存化手动缓存,python,memoization,Python,Memoization,我正在构建一个带记忆的Python Fibonacci函数的手动缓存版本,我注意到在递归调用中没有将缓存作为参数传递 但是,该功能仍然可以工作,因为它比非记忆版本快得多 当我将缓存作为函数参数添加时,算法速度更快,但不是很明显 有人能帮我理解为什么第一个版本可以工作,第二个版本是否更正确 import time def fib_cache(n, cache={}): if n in cache: return cache[n] if n == 0 or n =

我正在构建一个带记忆的Python Fibonacci函数的手动缓存版本,我注意到在递归调用中没有将缓存作为参数传递

但是,该功能仍然可以工作,因为它比非记忆版本快得多

当我将缓存作为函数参数添加时,算法速度更快,但不是很明显

有人能帮我理解为什么第一个版本可以工作,第二个版本是否更正确

import time


def fib_cache(n, cache={}):
    if n in cache:
        return cache[n]
    if n == 0 or n == 1:
        return n
    result = fib_cache(n - 1) + fib_cache(n - 2)
    cache[n] = result
    return result


def fib_cache2(n, cache={}):
    if n in cache:
        return cache[n]
    if n == 0 or n == 1:
        return n
    result = fib_cache2(n - 1, cache) + fib_cache2(n - 2, cache)
    cache[n] = result
    return result

start = time.perf_counter()
fib_cache(30)
end = time.perf_counter()
print("Version 1. Seconds taken: {:.5f}".format(end - start))

start = time.perf_counter()
fib_cache2(30)
end = time.perf_counter()
print("Version 2. Seconds taken: {:.5f}".format(end - start))

这是因为Python中的
def
只执行一次,默认变量只初始化一次。对于引用类型,这可能导致错误/意外行为。解决办法之一是:

def fib_cache3(n, cache=None):
    if cache is None:
        cache = {}
    if n in cache:
        return cache[n]
    if n == 0 or n == 1:
        return n
    result = fib_cache3(n - 1, cache) + fib_cache3(n - 2, cache)
    cache[n] = result
    return result

此版本的优点是它不依赖于引用类型的默认初始化,并且在函数执行后允许垃圾收集。

这是否回答了您的问题?这很有帮助。如果能解释一下这三个版本是如何表现出不同的行为,那就更有帮助了。