匠心精神 - 良心品质腾讯认可的专业机构-IT人的高薪实战学院

咨询电话:4000806560

Python里的10个缓存技巧,让你的程序运行更加流畅!

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程序的性能和效率。