Python高级编程:Functools模块的8个高级用法,强烈建议添加到你的开发工具箱中!

目录

1. functools.partial

2. functools.lru_cache

lru_cache的特点

cache的特点

性能比较与选择

3. functools.reduce

functools.reduce的作用

工作原理

示例

累加序列中的所有元素

计算阶乘

initializer的使用

应用场景

示例:计算平均销售额

小结

4. functools.update_wrapper

应用场景

5. functools.wraps

灵活性和自定义控制

低级控制和组合

理解装饰器实现细节

小结

6. functools.total_ordering

functools.total_ordering的作用

原理与实现

应用场景

小结

7. functools.singledispatch

functools.singledispatch的作用

原理与实现

应用场景

使用singledispatchmethod装饰类方法

小结

8. functools.cached_property (Python 3.8+)

functools.cached_property的作用

functools.cached_property的实现原理

详细示例

应用场景

注意事项

小结

结论



Python 是一门多功能语言,其众多优点之一就是它有很多功能强大的内置模块,这些模块使我们程序员在很多时候不用重复造轮子。functools 模块就是这样一个典型的例子。充分利用它可以让我们的 Python 代码更整洁、清晰和专业。

本文将介绍 Python 这个杰出模块的 8 个必知用途。阅读后,相信你能够在“Python 大师”的路上更进一步。

1. functools.partial

创建一个函数的新版本,并固定部分参数,减少重复传递参数的次数。类似于方法重写。

Python 有很多易用的内置函数,但是有时候对于特殊的案例我们必须向它们添加特定的参数。比如,int() 函数可以用于将字符串转换为整数。如果待转换的字符串是一个二进制整数的话,我们必须添加第二个参数:

print(f"The binary integer 101101 is equal: {int('101101', base=2)}")
# The binary integer 101101 is equal: 45

如果我们需要频繁地使用这个二进制转换功能,却总是重复写入相同的第二个参数,那将是很烦人的(同时看起来也是蠢蠢的)。

那么有没有一种方法可以让我们一处实现多处使用呢?functools 中的 partial 方法刚好可以帮助我们达到这个目的,让我们的代码变得更简洁:

from functools import partial

binary_trans = partial(int, base=2)
print(f"101101 (base 2) is equal to: {binary_trans('101101')} (base 10)")
print(f"1111110 (base 2) is equal to: {binary_trans('1111110')} (base 10)")
print(f"11111111 (base 2) is equal to: {binary_trans('11111111')} (base 10)")

输出结果如下:

101101 (base 2) is equal to: 45 (base 10)
1111110 (base 2) is equal to: 126 (base 10)
11111111 (base 2) is equal to: 255 (base 10)

这样一来,不管后续调用多少次,我们都不必给出第二个参数,实现定制化转换功能。当然,对于自定义函数,也同样可以使用 partial 方法。

from functools import partial

def multiply(x, y):
    return x * y

double = partial(multiply, 2)
print(double(5))  # 输出 10

这里的 partial 实现了某个数值 2 倍的定制化计算功能。

2. functools.lru_cache

使用最近最少使用(Least Recently Used, LRU)缓存装饰器,提高函数的性能,尤其适用于计算密集型或 I/O 密集型函数。

下面看一个常见的例子,即斐波那契数列数字的计算,我们分别用常规方法和缓存方法实现,看看它们之间的性能差距:

from functools import lru_cache
import timeit

def fibonacci_norm(n):
    if n < 2:
        return n
    return fibonacci_norm(n - 1) + fibonacci_norm(n - 2)

@lru_cache(maxsize=32)
def fibonacci_lru_cached(n):
    if n < 2:
        return n
    return fibonacci_lru_cached(n - 1) + fibonacci_lru_cached(n - 2)

def timed_fibonacci_norm():
    resutl = fibonacci_norm(30)
    return resutl

def timed_fibonacci_cached():
    resutl = fibonacci_lru_cached(30)
    # 清除缓存结果
    fibonacci_lru_cached.cache_clear()
    return resutl

if __name__ == '__main__':
    time_norm = timeit.timeit(timed_fibonacci_norm, number=50)
    time_cached = timeit.timeit(timed_fibonacci_cached, number=50)
    print(f'Average time for fibonacci (norm): {time_norm / 50} s')
    print(f'Average time for fibonacci (cached): {time_cached / 50} s')
    print(f'Cached version is faster than norm: {time_norm / time_cached / 50}')

执行结果如下:

Average time for fibonacci (norm): 0.1954923020000024 s
Average time for fibonacci (cached): 1.077199999599543e-05 s
Cached version is faster than norm: 362.9637988724064

从上面的结果可以看出,相较于常规方法,使用 lru_cache 方法速度快了大约 363 倍,对性能的提升非常显著。而且随着计算数字的增大,这个差距还会继续扩大。

此外,缓存方法还有另一种实现方式,即 cache 装饰器。其实现方式与 lru_cache 类似。我们可以看看它与常规方法的性能差距:

from functools import cache
import timeit

@cache
def fibonacci_cached(n):
    if n < 2:
        return n
    return fibonacci_cached(n - 1) + fibonacci_cached(n - 2)

def timed_fibonacci_cached():
    resutl = fibonacci_lru_cached(30)
    # 重新装饰函数以清楚缓存
    fibonacci_cached = cache(fibonacci_lru_cached)
    return resutl
    
if __name__ == '__main__':
    time_norm = timeit.timeit(timed_fibonacci_norm, number=50)
    time_cached = timeit.timeit(timed_fibonacci_cached, number=50)
    print(f'Average time for fibonacci (norm): {time_norm / 50} s')
    print(f'Average time for fibonacci (cached): {time_cached / 50} s')
    print(f'Cached version is faster than norm: {time_norm / time_cached / 50}')

可以看出,cache 的性能更好,比常规方法快了约 1213 倍,主要是因为 lru_cache 存在缓存策略,所以在缓存管理上会有一定开销。

lru_cache 和 cache 各有其优点和适用场景,性能上的差异主要取决于具体的使用场景和缓存策略的需求。下面是一些对比和选择建议:

lru_cache的特点

  • LRU 缓存策略lru_cache 使用最近最少使用(Least Recently Used, LRU)策略,当缓存达到最大容量时,会自动清除最久未使用的条目。这对于需要限制缓存大小并且期望自动管理缓存淘汰的场景非常有用。

  • 缓存统计信息lru_cache 提供缓存命中率等统计信息(通过 cache_info 方法),有助于监控和优化缓存使用。

  • 性能:在缓存大小有限且需要频繁访问缓存条目的情况下,lru_cache 能够显著提升性能,但在缓存管理上会有一定的开销。

cache的特点

  • 无缓存策略cache 是一个简单的无策略缓存,它没有缓存淘汰机制,即缓存条目会一直保留,直到程序终止或显式清除。这适合于需要缓存所有结果且不需要考虑内存限制的场景。

  • 性能cache 的性能开销较小,因为它没有管理缓存条目的开销,在没有内存限制和缓存淘汰需求的情况下,cache 可以提供更好的性能。

性能比较与选择

  • 内存限制:如果你的应用需要限制内存使用,并且缓存数据量可能很大,选择 lru_cache 更为合适,因为它能够自动管理缓存大小并清除旧条目。

  • 缓存条目数量少:如果缓存的数据量较少,且不会超出内存限制,使用 cache 会更加简单高效,因为它没有缓存管理的开销。

  • 缓存管理需求:如果你需要了解缓存的使用情况和命中率,lru_cache 提供的统计信息会很有帮助。

  • 性能测试:对于特定应用场景,可以通过实际测试来比较两者的性能。可以使用 timeit 模块进行多次调用的时间测量,评估两者在实际应用中的表现。

3. functools.reduce

functools.reduce 是 Python 很重要的高阶函数之一,它用于对可迭代对象中的元素进行累计操作,最终将其简化为单一的值。reduce 可以说是一个“归约”函数,通过对序列中的元素依次应用指定的二元操作,将序列归约为一个值。

functools.reduce的作用

reduce 的作用是对序列进行二元操作,并将序列简化为一个单一的值。它的使用格式如下:

from functools import reduce

result = reduce(function, iterable[, initializer])
  • function:一个接受两个参数的函数,reduce 会将其应用于 iterable 的元素。

  • iterable:一个可迭代对象(如列表、元组等)。

  • initializer(可选):初始值,如果提供,则首先将其与序列的第一个元素一起传递给

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/713446.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不可不知的Java SE技巧:如何使用for each循环遍历数组

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

【面试题】MySQL常见面试题总结

备战实习&#xff0c;会定期给大家整理常考的面试题&#xff0c;大家一起加油&#xff01; &#x1f3af; 系列文章目录 【面试题】面试题分享之JVM篇【面试题】面试题分享之Java并发篇【面试题】面试题分享之Java集合篇&#xff08;三&#xff09; 注意&#xff1a;文章若有错…

StarNet实战:使用StarNet实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 https://arxiv.org/pdf/2403.19967 论文主要集中在介绍和分析一种新兴的学习范式——星操作&#xff08;Star Operation&#xff09;&#xff0c;这是一种通过元素级乘法融合不同子…

[大模型]XVERSE-7B-chat langchain 接入

XVERSE-7B-Chat为XVERSE-7B模型对齐后的版本。 XVERSE-7B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;参数规模为 70 亿&#xff0c;主要特点如下&#xff1a; 模型结构&#xff1a;XVERSE-7B 使用主流 Deco…

echarts学习:通过图例事件实现选中后控制多条折线的显隐

1.问题描述 我在工作中遇到了这样一个需求&#xff1a;我们都知道点击echarts折线图的图例&#xff0c;是可以控制折线的显隐的。我现在希望点击某一个图例可以改变多条折线的显隐。 例如在下面这张图中&#xff0c;我将“xxx水位”和“yyy水位”分为一组&#xff1b;将“xxx…

521. 最长特殊序列 Ⅰ(Rust单百解法-脑筋急转弯)

题目 给你两个字符串 a 和 b&#xff0c;请返回 这两个字符串中 最长的特殊序列 的长度。如果不存在&#xff0c;则返回 -1 。 「最长特殊序列」 定义如下&#xff1a;该序列为 某字符串独有的最长 子序列 &#xff08;即不能是其他字符串的子序列&#xff09; 。 字符串 s …

【云原生】docker swarm 使用详解

目录 一、前言 二、容器集群管理问题 2.1 docker集群管理问题概述 2.1.1 docker为什么需要容器部署 2.2 docker容器集群管理面临的挑战 三、docker集群部署与管理解决方案 四、Docker Swarm概述 4.1 Docker Swarm是什么 4.1.1 Docker Swarm架构图 4.1.2 Docker Swarm几…

【MySQL】在CentOS环境下安装MySQL

目录 一、卸载残留环境 二、获取官方yum源 三、安装yum源 四、安装MySQL 五、启动MySQL 一、卸载残留环境 输入 ps axj | grep mysql 查看是否存在正在运行的MySQL服务 如果有&#xff0c;则先输入 systemctl stop mysqld 来关闭服务 然后输入 rpm -qa | grep mysql 查看…

Docker MySQL Shutting down mysqld

6月初至6月15日发现MySQL无故停机多次&#xff0c;导致系统无法使用。接下来各种日志查看&#xff0c;排查原因。先附上一份Docker种MySQL的日志的截图。 一、根据Docker的日志初步估计是数据库内存飙升&#xff0c;从而被系统杀掉进程 查询Linux系统日志&#xff0c;在宿主机…

Python武器库开发-武器库篇之Mongodb未授权漏洞扫描器(五十六)

Python武器库开发-武器库篇之Mongodb未授权漏洞扫描器(五十六) MongoDB 未授权访问漏洞简介以及危害 MongoDB是一款非常受欢迎的开源NoSQL数据库&#xff0c;广泛应用于各种Web应用和移动应用中。然而&#xff0c;由于默认配置的不当或者管理员的疏忽&#xff0c;导致不少Mon…

常用串口助手推荐

串口助手作为嵌入式软件工程师最常用的工具&#xff0c;相信大部分的同学都不陌生&#xff0c;这里就不介绍它的使用啦&#xff0c;介绍介绍有哪些好用的款。感兴趣的小伙伴也可以自己去写一个串口助手。 一、SSCOM5.13.1 站内下载资源&#xff1a; https://download.csdn.n…

51单片机STC89C52RC——2.2 独立按键控制LED亮灭Plus

目的 当独立K1按键按一下&#xff08;立即松开&#xff09;&#xff0c;LED D1点亮。再按一下K1&#xff08;立即松开&#xff09;LED D1熄灭。 与前一节《51单片机STC89C52RC——2.1 独立按键控制LED亮灭》当独立K1按键按下时LED D1 点亮&#xff0c;松开D1熄灭 效果不一…

PyTorch 张量数据类型

【数据类型】Python 与 PyTorch 常见数据类型对应&#xff1a; 用 a.type() 获取数据类型&#xff0c;用 isinstance(a, 目标类型) 进行类型合法化检测 >>> import torch >>> a torch.randn(2,3) >>> a tensor([[-1.7818, -0.2472, -2.0684],[ 0.…

单片机与DHT11温湿度检测设计

本次设计是采用STC89C54单片机加上低成本的温湿度模块DHT11构成的温湿度检测系统。设计主要由硬件与软件两部分设计构成。硬件方面包括单片机STC89C54、温湿度模块DHT11、显示模块LCD1602、电池电源、I2C存储器以及控制按键等5个部分。此系统完全基于单片机最小系统并进行一定的…

Open vSwitch 中 vswitchd 事件上报

一、数据包转发流程与 vswitchd 事件上报 Open vSwitch 的数据包转发流程如下图所示&#xff1a; 在数据包的转发流程中&#xff0c;提到过慢速路径的概念&#xff1a;即当数据包在内核空间无法完全处理时&#xff0c;会产生 upcall 调用&#xff0c;将数据包从内核空间转发到用…

XGBoost预测及调参过程(+变量重要性)--血友病计数数据

所使用的数据是血友病数据&#xff0c;如有需要&#xff0c;可在主页资源处获取&#xff0c;数据信息如下&#xff1a; 读取数据及数据集区分 数据预处理及区分数据集代码如下&#xff08;详细预处理说明见上篇文章--随机森林&#xff09;&#xff1a; import pandas as pd im…

RPG游戏完整指南

环境&#xff1a;unity2021urp 本教程教大家如何使用Unity创建一个RPG游戏&#xff0c;玩家可以在城镇场景中进行导航并寻找战斗&#xff0c;并在战斗中遇到不同类型的敌人。玩家可以向敌人施加不同的动作&#xff0c;如&#xff1a;常规攻击和撤离。这会是一个十分有趣的体验。…

AI时代新爬虫:网站自动转LLM数据,firecrawl深度玩法解读

在大模型的时代&#xff0c;爬虫技术也有了很多新的发展&#xff0c;最近出现了专门针对大模型来提取网站信息的爬虫&#xff0c;一键将网页内容转换为LLM-ready的数据。今天我们介绍其中的开源热门代表&#xff1a;firecrawl。 firecrawl 是什么 FireCrawl是一款创新的爬虫工…

数据资产治理与数据质量提升:构建完善的数据治理体系,确保数据资产的高质量与准确性

一、引言 随着信息技术的迅猛发展&#xff0c;数据已经成为企业和社会发展的重要资产。然而&#xff0c;数据资产的有效治理与数据质量的提升&#xff0c;是企业实现数字化转型、提升竞争力的关键。本文旨在探讨数据资产治理与数据质量提升的重要性&#xff0c;并提出构建完善…

开源高效API管理工具:RAP

RAP&#xff1a;简化API开发&#xff0c;提升团队协作效率- 精选真开源&#xff0c;释放新价值。 概览 RAP&#xff08;RESTful API Project&#xff09;是一个开源的API管理工具&#xff0c;由阿里巴巴团队开发并维护。它旨在帮助前后端开发人员通过一个统一的平台来设计、开…