Python里的10个缓存技巧,让你的程序运行更加流畅!
在Python开发中,缓存技巧是提高程序性能的关键。缓存是一种数据结构,可以存储一些常用的计算结果,避免重复计算。本文将介绍10种常见的缓存技巧,让你的Python程序运行更加流畅!
1.使用lru_cache装饰器
lru_cache是Python3.2中引入的一个装饰器,可以自动缓存函数的计算结果。在函数中使用该装饰器,可以在之后的调用中避免重复计算相同的输入参数。
举例来说,我们可以定义一个斐波那契数列函数,并使用lru_cache装饰器来缓存之前的计算结果:
```python
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
```
这样,之后调用fibonacci函数时,就可以避免重复计算相同的n,从而提高程序效率。
2.使用字典缓存计算结果
除了lru_cache外,我们也可以手动使用字典来缓存计算结果。比如,我们可以定义一个函数,用来计算斐波那契数列,并用字典来缓存计算结果:
```python
fib_cache = {}
def fibonacci(n):
if n in fib_cache:
return fib_cache[n]
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
fib_cache[n] = result
return result
```
这样,之后调用fibonacci函数时,如果之前已经计算过相同的n,就可以直接返回缓存的结果,从而避免重复计算。
3.使用lru_cache和字典混合缓存
另外,我们也可以结合使用lru_cache和字典来缓存计算结果。这种方法可以充分利用lru_cache的自动缓存机制,同时也可以手动管理缓存。
```python
from functools import lru_cache
fib_dict = {}
@lru_cache(maxsize=None)
def fibonacci(n):
if n in fib_dict:
return fib_dict[n]
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
fib_dict[n] = result
return result
```
这样,对于之前计算过的n,lru_cache会自动缓存其计算结果,而对于之前未计算过的n,我们手动将其计算结果加入字典缓存中,从而达到更高的缓存效率。
4.使用FIFO缓存替换策略
除了lru_cache外,我们也可以手动指定缓存替换策略。比如,我们可以实现一个FIFO缓存替换策略,即先进先出。
```python
class FifoCache:
def __init__(self, max_size=1000):
self.max_size = max_size
self.cache = {}
self.queue = []
def __getitem__(self, key):
return self.cache[key]
def __setitem__(self, key, value):
if len(self.queue) >= self.max_size:
old_key = self.queue.pop(0)
del self.cache[old_key]
self.cache[key] = value
self.queue.append(key)
```
这样,对于需要缓存的计算结果,我们可以将其保存到FifoCache对象中:
```python
fib_cache = FifoCache(max_size=100)
def fibonacci(n):
if n in fib_cache:
return fib_cache[n]
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
fib_cache[n] = result
return result
```
5.使用LRU缓存替换策略
除了FIFO缓存替换策略外,我们还可以使用LRU缓存替换策略,即最近最少使用。Python中已经内置了LRU缓存替换策略,可以通过functools模块中的lru_cache装饰器来使用。
6.使用TTL缓存过期策略
另外,我们也可以使用TTL缓存过期策略,即按照时间来设定缓存的有效期。比如,我们可以实现一个TTL缓存类:
```python
import time
class TtlCache:
def __init__(self, max_size=1000, ttl=60):
self.max_size = max_size
self.ttl = ttl
self.cache = {}
def __getitem__(self, key):
value, expired_time = self.cache[key]
if time.time() > expired_time:
del self.cache[key]
raise KeyError("Key not found")
return value
def __setitem__(self, key, value):
self.cache[key] = (value, time.time()+self.ttl)
if len(self.cache) > self.max_size:
oldest_key = min(self.cache.keys(), key=lambda k: self.cache[k][1])
del self.cache[oldest_key]
```
这样,我们就可以按照一定的时间来设置缓存的有效期:
```python
fib_cache = TtlCache(max_size=100, ttl=60)
def fibonacci(n):
if n in fib_cache:
return fib_cache[n]
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
fib_cache[n] = result
return result
```
7.使用手动缓存失效策略
除了TTL缓存过期策略外,我们还可以手动设置缓存失效策略。比如,我们可以在缓存中保存计算结果的时间戳,每次查询缓存时判断时间戳是否过期。
```python
class ManualExpireCache:
def __init__(self, max_size=1000, ttl=60):
self.max_size = max_size
self.ttl = ttl
self.cache = {}
def __getitem__(self, key):
value, expired_time = self.cache[key]
if time.time() > expired_time:
del self.cache[key]
raise KeyError("Key not found")
return value
def __setitem__(self, key, value):
self.cache[key] = (value, time.time()+self.ttl)
if len(self.cache) > self.max_size:
oldest_key = min(self.cache.keys(), key=lambda k: self.cache[k][1])
del self.cache[oldest_key]
def set_ttl(self, key, ttl):
value, _ = self.cache[key]
self.cache[key] = (value, time.time()+ttl)
```
这样,我们就可以通过手动设置缓存失效时间,来达到更高的缓存效率:
```python
fib_cache = ManualExpireCache(max_size=100, ttl=60)
def fibonacci(n):
if n in fib_cache:
return fib_cache[n]
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
fib_cache[n] = result
fib_cache.set_ttl(n, 60)
return result
```
8.使用多级缓存策略
除了单个缓存策略外,我们还可以使用多级缓存策略。比如,我们可以使用内存缓存和硬盘缓存来存储计算结果。当内存缓存满了之后,可以将一部分计算结果存放到硬盘缓存中。
```python
from functools import lru_cache
import shelve
mem_cache = {}
def disk_cache(key, value):
with shelve.open("cache.db") as cache:
cache[key] = value
@lru_cache(maxsize=None)
def fibonacci(n):
key = str(n)
if key in mem_cache:
return mem_cache[key]
if key in disk_cache:
result = disk_cache[key]
mem_cache[key] = result
else:
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
mem_cache[key] = result
disk_cache(key, result)
return result
```
这样,对于已经计算过的n,可以先从内存缓存中查询,如果内存缓存满了,则可以从硬盘缓存中查询。对于未计算过的n,可以先计算并缓存到内存中,如果内存满了,则可以缓存到硬盘中。
9.使用并发缓存策略
除了多级缓存策略外,我们还可以使用并发缓存策略。比如,我们可以使用多线程或者多进程来并发地计算和缓存计算结果。
```python
from functools import lru_cache
import threading
fib_cache = {}
@lru_cache(maxsize=None)
def fibonacci(n):
if n in fib_cache:
return fib_cache[n]
if n < 2:
result = n
else:
t1 = threading.Thread(target=fibonacci, args=(n-1,))
t2 = threading.Thread(target=fibonacci, args=(n-2,))
t1.start()
t2.start()
t1.join()
t2.join()
result = fib_cache[n-1] + fib_cache[n-2]
fib_cache[n] = result
return result
```
这样,我们可以在计算斐波那契数列时,同时启动两个线程来计算n-1和n-2的值,从而提高计算速度。
10.使用分布式缓存策略
最后,我们还可以使用分布式缓存策略。比如,我们可以使用Redis或者Memcached等分布式缓存系统,来缓存计算结果。
```python
import redis
r = redis.Redis(host="localhost", port=6379)
@lru_cache(maxsize=None)
def fibonacci(n):
value = r.get(str(n))
if value:
return int(value)
if n < 2:
result = n
else:
result = fibonacci(n-1) + fibonacci(n-2)
r.set(str(n), str(result))
return result
```
这样,我们可以将计算结果缓存到Redis中,从而实现分布式缓存,并提高计算效率。
总结
缓存技巧是Python开发中提高程序性能的重要手段。在本文中,我们介绍了10种常见的缓存技巧,包括使用lru_cache装饰器、使用字典缓存计算结果、使用lru_cache和字典混合缓存、使用FIFO缓存替换策略、使用LRU缓存替换策略、使用TTL缓存过期策略、使用手动缓存失效策略、使用多级缓存策略、使用并发缓存策略以及使用分布式缓存策略。这些技巧可以根据实际情况灵活使用,帮助我们提高Python程序的性能和效率。