【发布时间】:2010-12-01 15:46:03
【问题描述】:
让我们有一个方法可以缓存它计算的结果。
“如果”方法:
def calculate1(input_values):
if input_values not in calculate1.cache.keys():
# do some calculation
result = input_values
calculate1.cache[input_values] = result
return calculate1.cache[input_values]
calculate1.cache = {}
“除外”方法:
def calculate2(input_values):
try:
return calculate2.cache[input_values]
except AttributeError:
calculate2.cache = {}
except KeyError:
pass
# do some calculation
result = input_values
calculate2.cache[input_values] = result
return result
“get/has”方法:
def calculate3(input_values):
if not hasattr(calculate3, cache):
calculate3.cache = {}
result = calculate3.cache.get(input_values)
if not result:
# do some calculation
result = input_values
calculate3.cache[input_values] = result
return result
还有其他(更快)的方法吗?哪一个最pythonic?你会用哪一个?
注意:存在速度差异:
calculate = calculateX # depening on test run
for i in xrange(10000):
calculate(datetime.utcnow())
结果time python test.py:
calculate1: 0m9.579s
calculate2: 0m0.130s
calculate3: 0m0.095s
【问题讨论】:
-
您的基准测试对我来说看起来很可疑 - 我不相信第三种方法快 100 倍。您是否有机会重用第一次运行时的缓存?
-
使用键确实会变慢,至少在 python 2 中(它生成一个列表)。这也意味着线性搜索。为什么TF不只使用
input_values not in calculate1.cache?这是一个简单的哈希查找,并且可能与其他哈希查找相近(例如, -
如果你想测量 Python 代码的执行时间,你可以使用
timeit模块,它可能会给你比time更准确的答案。 -
您的基准测试似乎不合适;至少在我的系统上没有使用缓存中的值,因为每个循环需要超过一微秒。添加 print len(calculate.cache) 并尝试偶尔检查缓存。也许 datetime.utcnow().microsecond % 500
-
嗯;我只是不认为如果你只是想做的是记忆,那么 defaultdict 特别会有所帮助。并且 memoization 可能最好在 python 中使用装饰器类来完成。见下文。
标签: python coding-style performance