有什么做ppt的网站,网站提交至google,宁德seo优化,做复刻衣服买网站原文#xff1a;towardsdatascience.com/how-to-boost-the-performance-of-python-using-the-caching-techniques-156368d191e8 一旦你不再是 Python 新手#xff0c;那就该探索 Python 中的内置特性了。我敢打赌#xff0c;Python 中会有很多出人意料的内置特性。今天…原文towardsdatascience.com/how-to-boost-the-performance-of-python-using-the-caching-techniques-156368d191e8一旦你不再是 Python 新手那就该探索 Python 中的内置特性了。我敢打赌Python 中会有很多出人意料的内置特性。今天我将在这篇文章中介绍其中之一。你是否遇到过函数必须多次执行且某些结果可以重用的场景在下面的第一个例子中你会看到缓存机制将递归函数的性能提高了 120 倍。因此在这篇文章中我将介绍 Python 3.2 版本以来就内置的functools模块中的lru_cache装饰器。在functools模块中还有一个名为cache的装饰器它更加直接。然而易于使用有时意味着灵活性较低。所以我将从cache装饰器开始介绍它的局限性。然后将重点关注lru_cache如何为我们提供更多灵活性。1. cache 装饰器的回顾https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3fdfe21ccd603cab75706051c004f75c.png图片由作者在 Canva 中创建在我之前的一篇文章中我介绍了 Python 内置的functools模块中的cache装饰器。在那篇文章中我使用斐波那契递归函数来展示缓存机制的力量并且比没有缓存版本快了大约120 倍示例如下。让我们首先编写一个斐波那契递归函数。deffibonacci(n):ifn2:returnnreturnfibonacci(n-1)fibonacci(n-2)和大多数其他编程语言一样Python 也需要为递归函数构建一个“栈”并在每个栈上计算值。然而“cache”装饰器将显著提高性能。而且这样做并不困难。我们只需要从functools模块中导入它然后将装饰器添加到函数中。fromfunctoolsimportcachecachedeffibonacci_cached(n):ifn2:returnnreturnfibonacci_cached(n-1)fibonacci_cached(n-2)这里是运行结果和性能比较。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c84b9b74513f9e5efe314cfada86113c.png如果你想知道性能为什么有显著提升请查看下面的文章。如何使用 Python 内置装饰器显著提高性能使用 lru_cache 重新编写函数实际上我们并不真的需要“重写”任何东西。要使用lru_cache装饰器我们可以像使用cache装饰器一样简单地使用它。所以只有装饰器的名称发生了变化。fromfunctoolsimportlru_cachelru_cachedeffibonacci_cached(n):ifn2:returnnreturnfibonacci_cached(n-1)fibonacci_cached(n-2)可以看到类似的性能提升得到了重现。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/977fb811be70fb5ac11816dc6e2f2b53.png好的。现在你可能想知道为什么我们需要lru_cache以及它与cache装饰器的区别是什么接下来的部分将回答这些问题。2. “cache”的限制是什么https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6300398e5c09d2150c66c139a237fc52.pngCanva 中由作者创建的图片在我们开始介绍lru_cache装饰器之前我们需要了解cache装饰器的限制是什么。实际上主要的限制是内存问题。让我模拟一个用例。假设我们正在开发一个 API 端点从数据库获取用户详情。为了简单起见我将跳过所有步骤只定义一个返回随机用户的函数。所以如果你想直接尝试可以轻松地复制粘贴我的代码。importrandomimportstringimporttracemallocfromfunctoolsimportcachecachedefget_user_data(user_id):return{user_id:user_id,name:User str(user_id),email:fuser{user_id}example.com,age:random.randint(18,60),self-introduction:.join(random.choices(string.ascii_letters,k1000))}在上面的代码中使用了random模块来生成用户的年龄和自我介绍。为了模拟目的自我介绍只是一个包含随机字符的 1000 长度字符串。现在让我们编写一个模拟函数来调用这个get_user_data()函数。为了理解内存使用情况我们需要使用 Python 内置的tracemalloc模块。defsimulate(n):tracemalloc.start()_[get_user_data(i)foriinrange(n)]current,peaktracemalloc.get_traced_memory()print(fCurrent memory usage:{current/(1024**2):.3f}MB)tracemalloc.stop()因此我们运行get_user_data()函数n次。同时我们使用tracemalloc模块来跟踪内存使用情况。这里是10,000次模拟的内存使用情况内存使用量大约为14MB。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c80b9a1df2861e294de63016a1dcd83d.png这里是100,000次模拟的内存使用情况内存使用量大约为143MB。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/878ccb066602a9c92dc2859b9758ebbd.png这里是1,000,000次模拟的内存使用情况内存使用量大约为1421MB。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ac10c2a7575534ddd3d5d7b2d7ad346d.png更重要的是用于缓存的内存将永远不会释放直到进程停止。在现实场景中我们可能不知道我们需要多少内存来缓存。这可能导致无法控制的后果。我猜你已经意识到了这就是我们需要使用lru_cache的情况。为什么叫“lru”lru_cache装饰器中的“lru”代表“最近未使用”。这表示缓存机制使用的算法是通过保留频繁访问的数据并丢弃最少使用的数据来管理内存。等等这听起来我们可以为它可以缓存的最多数据添加一个上限。是的这正是lru_cache可以给我们提供的灵活性。3. 控制最大内存大小https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/65275cc1ea8d4b35d359e129fb7298fc.pngCanva 中由作者创建的图片现在让我们看看如何控制最大内存大小。我们可以重用之前的get_user_data()函数进行比较。当然为了演示目的我们需要对之前的例子做一些修改。首先我们需要导入lru_cache并在函数上使用这个装饰器。importrandomimportstringimporttracemallocfromfunctoolsimportlru_cachelru_cache(maxsize1000)defget_user_data(user_id):return{user_id:user_id,name:User str(user_id),email:fuser{user_id}example.com,age:random.randint(18,60),self-introduction:.join(random.choices(string.ascii_letters,k1000))}为了演示目的我将设置maxsize1000这样我们就可以比较带有内存控制的cache装饰器的内存使用情况。然后我们需要修改模拟函数。这次让我们每 100 次运行输出一次内存使用情况。defsimulate(n):tracemalloc.start()foriinrange(n):_get_user_data(i)ifi%1000:current,peaktracemalloc.get_traced_memory()print(fIteration{i}: Current memory usage:{current/(1024**2):.3f}MB)tracemalloc.stop()然后让我们模拟 2,000 次运行。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bff0a6f926ba37ed862ef88853123060.png显然前 1000 次运行表明内存使用在累积。之后对于 1001-2000 次运行内存使用变得稳定没有显著增加。下面的图表显示了增长趋势。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6d8a806933a01692a9d034c93bcbbd80.png因此当我们设置lru_cache的maxsize时在达到允许缓存的最高对象数量之前它将像cache装饰器一样工作。当达到上限时它将开始从最近最少使用的缓存对象中删除。这就是lru_cache更加灵活的原因因为它减轻了缓存的内存担忧。4. 缓存管理的更多工具https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/5d0d2e33438bf970c6e491e5ba73c3e4.pngCanva 作者创建的图片好的看到使用 Python 中的cache和lru_cache如此简单真是太好了。然而我们能否管理我们所缓存的任何内容设置最大大小确实是一个好方法但还有更多吗是的让我们看看缓存的两个控制函数。使用 cache_info()监控性能第一个有用的函数是cache_info()函数。它可以显示当前缓存的尺寸缓存数据被利用的次数命中以及从未被使用的次数未命中。让我们再次使用简单的斐波那契函数。fromfunctoolsimportlru_cachelru_cache(maxsize32)deffibonacci(n):ifn2:returnnreturnfibonacci(n-1)fibonacci(n-2)好的现在让我们运行函数并检查缓存信息。print(fibonacci(30))print(fibonacci.cache_info())https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/52ba5edc7789e1e69e9c2f710538cb43.png我们可以看到maxsize显示lru_cache的最大限制被设置为 32 个对象。已经有 31 个被使用缓存。在这 31 个缓存值中有 28 次命中。也有 31 次未命中这意味着有 31 次函数必须运行其逻辑来计算值因为没有缓存的值。看起来我们的缓存策略在这个函数中非常成功。cache_info()函数为我们提供了验证我们的缓存功能是否有所帮助的标准。例如如果命中次数很少而未命中次数很多这可能意味着该函数可能不值得缓存。使用 cache_clear()重置缓存。从其名称可以轻松猜出这个函数。是的一旦运行它它将清除所有缓存的成果。让我们再次使用斐波那契函数作为例子。fromfunctoolsimportlru_cachelru_cache(maxsize32)deffibonacci(n):ifn2:returnnreturnfibonacci(n-1)fibonacci(n-2)# Run the function and check the infoprint(fibonacci(30))print(fibonacci.cache_info())# Clear the cache and check the info againfibonacci.cache_clear()print(fibonacci.cache_info())在上述代码中我们只是再次运行了斐波那契函数。然后通过检查状态它显示与之前完全相同的统计数据当然。之后我们运行了cache_clear()函数来截断所有缓存的成果。现在让我们再次检查信息将不会留下任何东西。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/72bc13b5e10a71406263c45453c48493.png通过了解上述两个函数我们将能够更容易地管理我们的缓存。例如缓存的一个大问题是内存永远不会被释放但如果我们能定期或动态地清除缓存这个问题就可以得到缓解甚至解决。摘要https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/84f14212400521d1bf7fb40858a79e29.png由作者在 Canva 中创建的图像在这篇文章中我首先介绍了来自 Python 内置模块functools的cache装饰器。尽管它更容易使用但也有一些限制例如缺乏内存控制。相反lru_cache将为我们提供灵活性确保在更复杂的情况下不会出现内存泄漏。除了这些还介绍了一些其他技巧例如显示现有缓存的统计信息和清理缓存结果。通过有效地使用这些管理函数我们可以实现更定制的功能避免错误并更有效地利用内存。希望这篇文章能有所帮助