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

news2024/11/24 23:02:01

目录

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.coloradmin.cn/o/1827877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用PyTorch实现LSTM生成ai诗

最近学习torch的一个小demo。 什么是LSTM&#xff1f; 长短时记忆网络&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;旨在解决传统RNN在处理长序列时的梯度消失和梯度爆炸问题。LSTM引入了…

【C++高阶】C++继承学习手册:全面解析继承的各个方面

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模板进阶 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 继承 &#x1f4d6;1. 继承的概念及定义…

【云原生】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几…

摄影师在人工智能竞赛中与机器较量并获胜

摄影师在人工智能竞赛中与机器较量并获胜 自从生成式人工智能出现以来&#xff0c;由来已久的人机大战显然呈现出一边倒的态势。但是有一位摄影师&#xff0c;一心想证明用人眼拍摄的照片是有道理的&#xff0c;他向算法驱动的竞争对手发起了挑战&#xff0c;并取得了胜利。 迈…

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

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

Arnoldi Iteration 思考

文章目录 1. 投影平面2. Arnoldi Iteration3. python 代码 1. 投影平面 假设我们有一个向量q,我们需要关于向量q&#xff0c;构建一个投影平面P&#xff0c;使得给定任何向量v,可以通过公式 p P v pPv pPv&#xff0c;快速得到向量v在投影平面P上的投影向量p. 计算向量内积,…

Scala运算符及流程控制

Scala运算符及流程控制 文章目录 Scala运算符及流程控制写在前面运算符算数运算符关系运算符赋值运算符逻辑运算符位运算符运算符本质 流程控制分支控制单分支双分支多分支 循环控制for循环while循环循环中断嵌套循环 写在前面 操作系统&#xff1a;Windows10JDK版本&#xff…

redis源码编译安装

源码下载地址http://download.redis.io/releases/ 1 环境准备 安装编译环境 sudo yum install gcc -y gcc -v 查看版本 sudo yum -y install centos-release-scl sudo yum -y install devtoolset-10-gcc devtoolset-10-gcc-c devtoolset-10-binutils scl enable devtool…

马斯克在2024年特斯拉股东大会上的年度发言

马斯克表示&#xff0c;“如果市盈率是20或25倍&#xff0c;那就意味着&#xff0c;光是Optimus就能带来20万亿美元的市值。而自动驾驶汽车的市值可能在5到10万亿美元之间。因此&#xff0c;特斯拉的市值达到当今市值最高公司的10倍&#xff0c;是可以想象的&#xff0c;也是有…

【MySQL基础随缘更系列】DML语句

文章目录 一、表记录操作-上1.1、DML概述1.2、插入记录 二、表记录操作-下2.1、更新记录2.2、删除记录 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &a…

创新案例 | 3个关键策略:乳制品品牌认养一头牛如何通过私域流量运营获取1400万会员

探索认养一头牛如何运用创新的私域流量运营策略&#xff0c;在竞争激烈的乳制品市场中脱颖而出&#xff0c;实现会员数量的飞速增长至1400万。本文深入分析了其数据驱动的广告投放、高效的会员运营体系和创新的用户互动机制&#xff0c;为企业提供提升用户粘性和品牌忠诚度的宝…

第19章 大数据架构设计理论与实践

19.1 传统数据处理系统存在的问题 海量数据的&#xff0c;数据库过载&#xff0c;增加消息队列、甚至数据分区、读写分离、以及备份以及传统架构的性能的压榨式提升&#xff0c;都没有太明显的效果&#xff0c;帮助处理海量数据的新技术和新架构开发被提上日程。 19.2 大数据处…

设计模式——观察者模式(发布/订阅模式)

观察者模式(发布/订阅模式) 是一种行为模式&#xff0c;允许你定义一种订阅机制&#xff0c;可在对象事件发生时通知多个“观察”该对象的其他对象 观察者模式定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时&am…

springboot汽车配件管理系统(源码+sql+论文报告)

绪论 1.1 研究意义和背景 随着我国经济的持续发展&#xff0c;汽车已经逐步进入了家庭。汽车行业的发展&#xff0c;也带动了汽车配件行业的快速发展。 汽车配件行业的迅猛发展&#xff0c; 使得汽配行业的竞争越来越激烈。如何在激烈的竞争中取胜&#xff0c;是每家汽车零部…

【MYSQL】MYSQL操作库

1.数据库字符编码集/数据库校验集 当我们在数据库中保存数据时&#xff0c;需要存和取时候编码一致&#xff0c;比方说你用汉语保存的数据&#xff0c;当你读的时候为了避免乱码问题&#xff0c;也必须用汉语读&#xff0c;这就叫做数据库字符编码集一致。 当我们进行查找&…

基于单片机的太阳能无线 LED 灯设计

摘 要 &#xff1a; 文章设计一款太阳能 LED 灯 &#xff0c; 经过太阳能给锂电池充电 &#xff0c; 利用 51 单片机通过检测电路对整个系统施行管理和监控&#xff0c; 可以使用手机和 WIFI 作为通信工具 &#xff0c; 利用光敏电阻检测光照 &#xff0c; 进而控制灯的亮…

【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)

最终效果 文章目录 最终效果前言素材下载简单搭建环境控制小鸟生成弹簧 限制小鸟的控制范围弹簧线的显示隐藏飞行新增木头木头销毁不同血量的木头状态配置更多物品爆炸效果创建敌人的小猪创建多个小鸟循环游戏结束相机跟随加分特效不同定义技能的鸟加速鸟回旋鸟爆炸鸟效果 轨迹…

快手爬票概述

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 无论是出差还是旅行&#xff0c;都无法离开交通工具的支持。现如今随着科技水平的提高&#xff0c;高铁与动车成为人们喜爱的交通工具。如果想要知道…

【C#】图形图像编程

实验目标和要求&#xff1a; 掌握C#图形绘制基本概念&#xff1b;掌握C#字体处理&#xff1b;能进行C#图形图像综合设计。 运行效果如下所示&#xff1a; 1.功能说明与核心代码 使用panel为画板&#xff0c;完成以下设计内容&#xff1a; 使用pen绘制基础图形&#xff1b;使…

浅谈golang字符编码

1、 Golang 字符编码 Golang 的代码是由 Unicode 字符组成的&#xff0c;并由 Unicode 编码规范中的 UTF-8 编码格式进行编码并存储。 Unicode 是编码字符集&#xff0c;囊括了当今世界使用的全部语言和符号的字符。有三种编码形式&#xff1a;UTF-8&#xff0c;UTF-16&#…