在Python程序开发中,重复计算是拖慢程序运行的常见原因,尤其是当计算逻辑复杂、耗时较长时,多次执行相同的计算会浪费大量CPU资源。通过合理的优化手段避免重复计算,能够显著提升程序性能。

手动缓存中间结果
最基础的避免重复计算的方式是手动将已经计算过的结果存储起来,下次需要相同结果时直接从存储中读取,不需要重新执行计算逻辑。通常可以使用字典作为缓存容器,键为计算的输入参数,值为对应的计算结果。
以下是一个计算斐波那契数列的示例,未优化时每次调用都会重复计算大量子问题:
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
# 计算fib(10)需要多次重复计算子项
print(fib(10))
优化后的版本加入手动缓存:
# 定义缓存字典
fib_cache = {}
def fib_with_cache(n):
# 如果结果已经在缓存中,直接返回
if n in fib_cache:
return fib_cache[n]
# 否则执行计算
if n <= 1:
result = n
else:
result = fib_with_cache(n-1) + fib_with_cache(n-2)
# 将结果存入缓存
fib_cache[n] = result
return result
print(fib_with_cache(10))
print(fib_with_cache(10)) # 第二次调用直接读取缓存
使用functools.lru_cache装饰器
Python标准库的functools模块提供了lru_cache装饰器,能够自动为函数添加缓存功能,不需要手动编写缓存逻辑。它内部使用有序字典存储最近调用的结果,还可以指定缓存的最大大小,超出时会淘汰最久未使用的缓存项。
使用lru_cache改写斐波那契计算的示例:
from functools import lru_cache
@lru_cache(maxsize=128) # 最多缓存128个结果
def fib_lru(n):
if n <= 1:
return n
return fib_lru(n-1) + fib_lru(n-2)
print(fib_lru(10))
print(fib_lru(10)) # 直接返回缓存结果
# 查看缓存信息
print(fib_lru.cache_info())
cache_info()方法可以返回缓存的命中次数、未命中次数、当前缓存大小等信息,方便我们评估缓存的效果。
利用局部变量减少属性查找
另一种常见的重复计算场景是循环中反复访问对象的属性或全局变量,每次访问都需要额外的查找开销。可以将这些频繁使用的值保存到局部变量中,减少重复查找。
例如下面的代码在循环中反复访问全局的math.sin函数:
import math
def calc_sum1(nums):
total = 0
for num in nums:
# 每次循环都要查找math.sin
total += math.sin(num)
return total
优化后的版本将math.sin赋值给局部变量:
import math
def calc_sum2(nums):
total = 0
# 将常用函数保存到局部变量
sin_func = math.sin
for num in nums:
total += sin_func(num)
return total
不同场景的优化选择
不同的避免重复计算的方案适用于不同的场景:
- 如果是简单的函数结果缓存,优先使用
functools.lru_cache,代码简洁且功能完善 - 如果缓存逻辑有特殊需求,比如需要持久化缓存或者自定义淘汰策略,可以选择手动实现缓存逻辑
- 如果是循环中重复的属性、全局变量访问,优先使用局部变量保存的方式减少查找开销
在实际开发中,可以结合性能分析工具定位重复计算的瓶颈点,再选择对应的优化方案,避免盲目优化。