当前位置: 首页 > news >正文

Python中的装饰器`@functools.lru_cache`:用法、来源与应用 (中英双语)

今天看到一段源码 https://github.com/google-research/google-research/blob/master/instruction_following_eval/instructions_util.py 如下,对其中使用的装饰器函数感到好奇,所以产生了这篇博客。


@functools.lru_cache(maxsize=None)
def _get_sentence_tokenizer():return nltk.data.load("nltk:tokenizers/punkt/english.pickle")

Python中的@functools.lru_cache:用法、来源与应用

在Python中,@装饰器语法的标志,用于将一个函数包装进另一个函数中,扩展或修改其功能。functools.lru_cache是Python标准库functools模块提供的一个装饰器,用于缓存函数的返回值,提升性能。


1. 装饰器的来源与语法

装饰器(Decorators)是Python函数式编程的一个核心特性。其来源可以追溯到Python 2.4版本,主要目的是让代码更简洁、更易读。@符号将装饰器函数与目标函数绑定,简化代码调用。

  • 装饰器定义
    本质上,装饰器是一个接收函数作为参数并返回一个新函数的高阶函数

示例:

def decorator(func):def wrapper():print("装饰器已执行")return func()return wrapper@decorator  # 等价于 func = decorator(func)
def say_hello():print("Hello, World!")

更多关于python装饰器的内容,可以参考笔者的另一篇博客:什么是装饰器?以Python为例:Basic Usage of Decorators (中英双语)


2. functools.lru_cache的作用

functools.lru_cache 是一个用于缓存函数调用结果的装饰器。

  • LRU全称是Least Recently Used,即最近最少使用缓存策略。
  • 当函数被多次调用时,lru_cache会缓存函数的输入和输出,减少重复计算,提升效率。
参数说明
  • maxsize: 设置缓存大小(None表示无限制)。
  • typed: 是否区分输入参数的类型(默认为False)。

示例:

import functools@functools.lru_cache(maxsize=3)
def fibonacci(n):print(f"计算Fibonacci({n})")if n < 2:return nreturn fibonacci(n-1) + fibonacci(n-2)print(fibonacci(5))  # 计算结果缓存,重复调用时不会重新计算

输出示例:

计算Fibonacci(5)
计算Fibonacci(4)
计算Fibonacci(3)
计算Fibonacci(2)
计算Fibonacci(1)
计算Fibonacci(0)
5

3. 代码分析与解释

以下是https://github.com/google-research/google-research/blob/master/instruction_following_eval/instructions_util.py 提供的代码:

import functools
import nltkdef count_words(text):"""Counts the number of words."""tokenizer = nltk.tokenize.RegexpTokenizer(r"\w+")tokens = tokenizer.tokenize(text)num_words = len(tokens)return num_words@functools.lru_cache(maxsize=None)
def _get_sentence_tokenizer():return nltk.data.load("nltk:tokenizers/punkt/english.pickle")
代码解释:
  1. count_words函数

    • 用于统计文本中的单词数量。
    • 通过nltk库中的RegexpTokenizer按正则表达式匹配单词,返回token列表并计算长度。
  2. _get_sentence_tokenizer函数

    • 加载NLTK库的句子分割模型punkt
    • 使用@functools.lru_cache(maxsize=None)装饰,表示缓存该函数的返回值。
    • 好处:加载分词器的操作是耗时的,通过缓存,只需加载一次。

4. functools.lru_cache的应用场景

  • 递归函数:如斐波那契数列,避免重复计算。
  • I/O密集型函数:比如数据库查询、网络请求,缓存结果以减少耗时。
  • 大规模数据处理:缓存部分中间结果,提高性能。
  • 机器学习/自然语言处理:模型加载、分词器初始化等耗时操作。

示例:

@functools.lru_cache(maxsize=128)
def fetch_data_from_db(query):# 模拟数据库查询print("执行查询:", query)return f"结果_{query}"print(fetch_data_from_db("SELECT * FROM table"))
print(fetch_data_from_db("SELECT * FROM table"))  # 直接返回缓存结果

输出:

执行查询: SELECT * FROM table
结果_SELECT * FROM table
结果_SELECT * FROM table

5. 补充内容:查看缓存信息

functools.lru_cache 提供了缓存管理的方法:

  • cache_info():查看缓存命中率和状态。
  • cache_clear():清空缓存。

示例:

@functools.lru_cache(maxsize=2)
def add(a, b):return a + badd(1, 2)
add(3, 4)
add(5, 6)print(add.cache_info())  # 输出缓存状态
add.cache_clear()        # 清除缓存

总结

  1. 装饰器的语法@用来将装饰器与函数绑定。
  2. lru_cache作用:缓存函数结果,提升性能,避免重复计算。
  3. 实际应用:适用于递归计算、I/O密集型操作和数据处理任务。
  4. 代码示例:通过数值分析,展示了lru_cache的高效性。

通过合理使用functools.lru_cache,Python程序可以在性能瓶颈处得到极大提升。

英文版

Exploring @functools.lru_cache in Python

The @ symbol in Python is used for decorators, which allow you to modify or enhance the behavior of a function or method. One such decorator is functools.lru_cache, which caches a function’s return values for optimized performance, especially in repetitive or resource-intensive tasks.


What is lru_cache?

functools.lru_cache is part of Python’s functools module. LRU stands for Least Recently Used, a caching strategy that keeps only the most frequently or recently used results, removing older ones when the cache exceeds its size limit.

Key Syntax:

@functools.lru_cache(maxsize=None, typed=False)
Parameters:
  1. maxsize: The maximum number of results to cache. If set to None, the cache size is unlimited.
  2. typed: If True, different types of arguments (e.g., 1 vs. 1.0) will have separate cached results.

Code Example and Explanation

Here is an example of lru_cache in action: Source: https://github.com/google-research/google-research/blob/master/instruction_following_eval/instructions_util.py

import functools
import nltkdef count_words(text):"""Counts the number of words."""tokenizer = nltk.tokenize.RegexpTokenizer(r"\w+")tokens = tokenizer.tokenize(text)num_words = len(tokens)return num_words@functools.lru_cache(maxsize=None)
def _get_sentence_tokenizer():return nltk.data.load("nltk:tokenizers/punkt/english.pickle")
Breakdown:
  1. count_words:

    • Uses RegexpTokenizer from NLTK to split a text into tokens (words).
    • Computes and returns the word count.
  2. _get_sentence_tokenizer:

    • Loads NLTK’s pre-trained sentence tokenizer. This is resource-heavy if loaded multiple times.
    • Why use @lru_cache?:
      • With lru_cache, the tokenizer is loaded only once. Future calls retrieve it from the cache, saving time and memory.

How lru_cache Works

Internally, lru_cache uses a dictionary-like data structure to store results. When a function is called:

  1. The function’s arguments act as a unique key.
  2. If the result exists in the cache (cache hit), it is returned directly.
  3. If not (cache miss), the function computes the result, stores it in the cache, and returns it.

Practical Applications

  1. Recursive Calculations:

    @functools.lru_cache(maxsize=128)
    def fibonacci(n):if n < 2:return nreturn fibonacci(n - 1) + fibonacci(n - 2)
    

    In this example, repeated calls to the same input are avoided by caching results.

  2. Optimizing Expensive Operations: Tasks like API calls, database queries, or loading large models can benefit greatly from caching.


Why Use lru_cache?

  1. Performance Boost: Speeds up applications by avoiding redundant computations.
  2. Memory Efficiency: Automatically clears old entries when the cache limit is reached.
  3. Flexibility: It works with various types of functions and arguments.

Summary

@functools.lru_cache is a powerful tool for improving Python application efficiency. By caching results of expensive or repetitive function calls, it saves time and computational resources. Its ease of use and wide applicability make it an essential feature for developers.

后记

2024年12月16日19点49分于上海,在GPT4o大模型辅助下完成。

相关文章:

Python中的装饰器`@functools.lru_cache`:用法、来源与应用 (中英双语)

今天看到一段源码 https://github.com/google-research/google-research/blob/master/instruction_following_eval/instructions_util.py 如下&#xff0c;对其中使用的装饰器函数感到好奇&#xff0c;所以产生了这篇博客。 functools.lru_cache(maxsizeNone) def _get_sentenc…...

思维图(GoT):解锁大模型解决复杂问题的能力

今天分享的是苏黎世联邦理工学院、华沙理工大学和Cledar联合发表的一篇文章&#xff1a;思维图&#xff1a;用大语言模型解决复杂问题 论文题目&#xff1a;Graph of Thoughts: Solving Elaborate Problems with Large Language Models 论文链接&#xff1a;https://arxiv.or…...

使用winscp从windows访问Ubuntu进行文件传输

Ubuntu 系统上的准备工作 • 安装 SSH 服务器&#xff1a; 确保 Ubuntu 系统上已经安装了 SSH 服务器。如果没有安装&#xff0c;可以使用以下命令安装&#xff1a; sudo apt update sudo apt install openssh-server • 启动 SSH 服务&#xff1a; 确保 SSH 服务正在运行&a…...

Java全栈项目:实验室预约管理系统的设计与实现

一、项目介绍 实验室预约管理系统是一个基于Java全栈技术开发的Web应用系统&#xff0c;旨在提供便捷的实验室预约、管理和使用体验。本系统主要面向高校师生&#xff0c;实现实验室资源的智能化、信息化管理。 二、技术栈 前端技术 Vue.jsElement UIAxiosVue RouterVuex …...

使用 esrally race 测试 Elasticsearch 性能及 Kibana 可视化分析指南

前言&#xff1a; 在对 Elasticsearch 集群进行性能测试与调优的过程中&#xff0c;esrally 是官方推荐的测试工具。通过 esrally race 命令&#xff0c;我们可以模拟各种查询与索引负载&#xff0c;对集群进行基准测试。然而&#xff0c;仅看 esrally 的终端输出并不直观&…...

OpenAI 第七日 推出了一项新功能——ChatGPT的“Projects”

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

【小白51单片机专用教程】protues仿真AT89C51入门

课程特点 无需开发板0基础教学软件硬件双修辅助入门 本课程面对纯小白&#xff0c;因此会对各个新出现的知识点在实例基础上进行详细讲解&#xff0c;有相关知识的可以直接跳过。课程涉及protues基本操作、原理图设计、数电模电、kell使用、C语言基本内容&#xff0c;所有涉及…...

正则表达式——元字符匹配(单字符)

单字符匹配: ###注意事项&#xff1a;前面要加r&#xff1a;如(re.findall(r\w,字符串名)) #. :匹配任意一个字符 (.本身通过\.匹配) # [ ]: 匹配[ ]中的字符 # \d: 匹配数字 # \D: 匹配非数字 # \s: 匹配空白(空格) # \S:匹配非空白 # \w: 匹配单词字符&#xff08;a…...

快速在远程服务器执行命令、批量在多个服务器执行命令(基于sshpass的自定义脚本fastsh)

在日常服务器操作中&#xff0c;很多时候我们需要同时操作多个服务器。特别对于那些每个服务器都需要操作相同命令的场景&#xff0c;不断的切换命令会话窗口会比较麻烦。基于此&#xff0c;编写了本文中的 fastsh 脚本用于轻度解决这种问题&#xff0c;提高一定的便利性。 使…...

【中间件介绍及案例分析】

中间件介绍及案例分析 一、中间件的定义 中间件是一种位于操作系统、网络和数据库之上&#xff0c;应用软件之下的软件。它的主要作用是为处于不同系统中的软件组件提供通用服务&#xff0c;使得这些软件组件能够更好地通信、协同工作&#xff0c;并且帮助开发人员更高效地构…...

CRMEB PHP多商户版DOCKER部署实战

#首先&#xff0c;制作docker 镜像# 官方有一个镜像&#xff0c;但是拉不来下&#xff0c;也不知道是没是没有维护&#xff0c;嘎了。只能自己动手做一个。 这里选择ubuntu 24 为基础&#xff0c;制作crmeb-mer的镜像&#xff0c;Dockerfile内容如下&#xff1a; # 使用官方…...

Node.js基础入门

1.Node.js 简介 Node 是一个让 JavaScript (独立)运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。 发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。 简单的说 Node.js 就是运行在服务端的…...

Hive——HQL数据定义语言

文章目录 Hive HQL数据查询语言更多大数据资源持续更新中。。。学习目标一、HQL数据定义语言&#xff08;DDL&#xff09;概述1、DDL语法的作用2、Hive中DDL使用☆ 创建数据库☆ 查询数据库☆ 切换数据库☆ 修改数据库☆ 删除数据库 二、Hive DDL建表基础1、完整建表语法树2、H…...

vLLM 教程上新!覆盖从入门到进阶 4 种应用方式;中文文档同步上线,0 帧起手加速大模型推理

如今&#xff0c;大语言模型 (LLM) 的发展正在从规模参数迭代升级拓展至应用场景的适配与创新&#xff0c;在这个过程中&#xff0c;其也暴露出一系列问题。例如&#xff0c;在推理环节的效率较低&#xff0c;处理复杂任务时耗时较长&#xff0c;难以满足对实时性要求较高的场景…...

Kubernetes# RBAC访问控制

目录 定义 配置对象 Role ClusterRole ServiceAccount RoleBinding ClusterRoleBinding 配置示例 定义 Kubernetes的运行是由多种类型的资源组合起来&#xff0c;每种资源各司其职完成整个集群的功能。那么自然也需要一套机制控制资源的访问权限&#xff0c;保证安全性…...

如何实现后端返回excel文件,在前端下载功能

前言 简单记录一下&#xff0c;excel文件导出下载功能 一、后端接口返回excel文件 把自己生成的workbook 以文件流的方式&#xff0c;返回前台 Workbook workbook employeeConfirmationDefectService.exportPoorPolishExcel(budatBegin, budatEnd, queryWrapper);//传输到…...

编程:一场不设防的智慧江湖

在数字的汪洋中&#xff0c;有一片从未设置年龄禁区的领地——编程世界。许多人会问&#xff1a;35岁了&#xff0c;还能学编程吗&#xff1f;答案是&#xff1a;不仅能学&#xff0c;还能学得很精彩。 时光荏苒&#xff0c;科技浪潮汹涌澎湃。曾经&#xff0c;人们以为编程是…...

电脑游戏运行时常见问题解析:穿越火线提示“unityplayer.dll丢失”的修复指南

电脑游戏运行时常见问题解析&#xff1a;穿越火线提示“unityplayer.dll丢失”的修复指南 在探索电脑游戏的无限乐趣时&#xff0c;我们时常会遇到一些不期而遇的挑战。今天&#xff0c;我们将聚焦于一个常见的游戏运行错误——穿越火线&#xff08;或其他使用Unity引擎的游戏…...

【C++】CUDA线程在全局索引中的计算方式

文章目录 1. 一维网格一维线程块2. 二维网格二维线程块3. 三维网格三维线程块4. 不同组合形式4.1 一维网格一维线程块4.2 一维网格二维线程块4.3 一维网格三维线程块4.4 二维网格一维线程块4.5 二维网格二维线程块4.6 二维网格三维线程块4.7 三维网格一维线程块4.8 三维网格二维…...

【笔记】C语言转C++

网课链接&#xff1a;【C语言 转 C 简单教程】 https://www.bilibili.com/video/BV1UE411j7Ti/?p27&share_sourcecopy_web&vd_source4abe1433c2a7ef632aeed6a3d5c0b22a 网课老师B站id:别喷我id 视频总时长&#xff1a;01:55:27 以下笔记是我通过此网课整理 建议先…...

锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集

锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测&#xff0c;附锂电池最新文章汇集 目录 锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测&#xff0c;附锂电池最新文章汇集预测效果基本描述程序设计参考资料 预测效果 基本描述 锂电池SOH预测 | 基于Bi…...

半导体器件与物理篇5 1~4章课后习题

热平衡时的能带和载流子浓度 例 一硅晶掺入每立方厘米10^{16}个砷原子&#xff0c;求室温下(300K)的载流子浓度与费米能级。 需要用到的公式包括1.本征载流子浓度公式 2.从导带底算起的本征费米能级 2.从本征费米能级算起的费米能级 载流子输运现象 例1:计算在300K下&#x…...

Pytest-Bdd-Playwright 系列教程(16):标准化JSON报告Gherkin格式命令行报告

Pytest-Bdd-Playwright 系列教程&#xff08;16&#xff09;&#xff1a;标准化JSON报告&Gherkin格式命令行报告 前言一、创建Feature文件二、创建步骤定义文件三、生成Cucumber格式的JSON报告四、使用Gherkin格式的命令行报告五、将BDD报告集成到Jenkins中总结 前言 在自动…...

机器学习之学习范式

机器学习的四种主要范式分别是&#xff1a;监督学习、非监督学习、强化学习和半监督学习。以下是每种范式的详细介绍&#xff1a; 1. 监督学习&#xff08;Supervised Learning&#xff09; 定义&#xff1a; 通过已标注的数据训练模型&#xff0c;以预测或分类未知数据。 目…...

PHPstudy中的数据库启动不了

法一 netstat -ano |findstr "3306" 查看占用该端口的进程号 taskkill /f /pid 6720 杀死进程 法二 sc delete mysql...

鸿蒙开发-ArkTS 创建自定义组件

在 ArkTS 中创建自定义组件是一个相对简单但功能强大的过程。以下是如何在 ArkTS 中创建和使用自定义组件的详细步骤&#xff1a; 一、定义自定义组件 使用Component注解&#xff1a;为了注册一个组件&#xff0c;使其能够在其他文件中被引用&#xff0c;你需要使用Component…...

记录学习《手动学习深度学习》这本书的笔记(五)

这一章是循环神经网络&#xff0c;太难了太难了&#xff0c;有很多卡壳的地方理解了好久&#xff0c;比如隐藏层和隐状态的区别、代码的含义&#xff08;为此专门另写了一篇【笔记】记录对自主实现一个神经网络的步骤的理解&#xff09;、梯度计算相关&#xff08;【笔记】记录…...

【Qt】Qt+Visual Studio 2022环境开发

在使用Qt Creator的过程中&#xff0c;项目一大就会卡&#xff0c;所以我一般都是用VS开发Cmake开发&#xff0c; 在上一篇文章中&#xff0c;我已经安装了CMake&#xff0c;如果你没有安装就自己按一下。 记得配置Qt环境变量&#xff0c;不然CMake无法生成VS项目&#xff1a…...

云计算HCIP-OpenStack04

书接上回&#xff1a; 云计算HCIP-OpenStack03-CSDN博客 12.Nova计算管理 Nova作为OpenStack的核心服务&#xff0c;最重要的功能就是提供对于计算资源的管理。 计算资源的管理就包含了已封装的资源和未封装的资源。已封装的资源就包含了虚拟机、容器。未封装的资源就是物理机提…...

HCIA-Access V2.5_3_2_VLAN数据转发

802.1Q的转发原则--Access-Link 首先看一下Access,对于Access端口来说&#xff0c; 它只属于一个VLAN,它的VLANID等于PVID。 首先看一下接收方向&#xff0c;前面说过交换机内部一定要带标签转发&#xff0c;所以当交换机接收到一个不带tag的数据帧时&#xff0c;会给它打上端…...