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

本文主要是介绍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 partialbinary_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 partialdef multiply(x, y):
    return x * ydouble = 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 timeitdef fibonacci_norm(n):if n < 2:return nreturn fibonacci_norm(n - 1) + fibonacci_norm(n - 2)@lru_cache(maxsize=32)
def fibonacci_lru_cached(n):if n < 2:return nreturn fibonacci_lru_cached(n - 1) + fibonacci_lru_cached(n - 2)def timed_fibonacci_norm():resutl = fibonacci_norm(30)return resutldef timed_fibonacci_cached():resutl = fibonacci_lru_cached(30)# 清除缓存结果fibonacci_lru_cached.cache_clear()return resutlif __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 reduceresult = reduce(function, iterable[, initializer])
  • function:一个接受两个参数的函数,reduce 会将其应用于 iterable 的元素。

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

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

这篇关于Python高级编程:Functools模块的8个高级用法,强烈建议添加到你的开发工具箱中!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1066552

相关文章

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装