Python Functools模块

news/2025/1/26 15:28:04/文章来源:https://www.cnblogs.com/xuxiaobo/p/18691849

代码:

#coding=utf-8import functools
from functools import cache
from functools import cached_property, lru_cache
from functools import partial, partialmethod
from functools import singledispatch, singledispatchmethod
from functools import update_wrapper, wraps
from functools import reduce#################################################################
'''
@cache装饰器
它的主要作用是提高函数的执行效率,特别是在函数被多次调用且输入参数相同的情况下,避免重复计算,
如果一个函数在相同的输入参数下被多次调用,cache 会记住第一次调用的结果,并在后续调用中直接返
回缓存的结果,而不是重新计算。它是线程安全的,因此可以在多个线程中使用。
'''
def func_test_no_cache(n):print("执行no-cache")return n@cache
def func_test_cache(n):print("执行cache")return ndef test_cache():print("[test_cache:]")for i in range(3):func_test_no_cache(10)func_test_cache(10)print()#################################################################
'''
@cached_property装饰器
用于将一个类的无参方法转换为缓存属性,意味着该方法在第一次调用时会被计算并缓存结果,
后续调用时直接返回缓存的结果。缓存的结果是实例级别的,即每个实例都有自己的缓存。即使
后续改变了方法内部涉及的类参数,输出也结果不会发生改变。
'''
class CircleCache:def __init__(self, radius):self.radius = radius@cached_propertydef area(self):'''
        如果类本身存在area属性,则此方法不生效。也就是本身属性读取和写入优先于 cached_property 方法'''
        print("计算面积")return 3.14159 * self.radius ** 2def test_cached_property():print("[test_cached_property:]")# 创建 Circle 对象circle = CircleCache(5)# 第一次访问 area 属性时会计算并缓存结果print(circle.radius, circle.area)del circle.radiuscircle.radius = 60'''
    第二次访问 area 属性时直接返回缓存的结果,即使是中途改变了圆的半径或者是删除了参与计算的参数。'''
    print(circle.radius, circle.area)print()#################################################################
'''
@lru_cache装饰器
lru_cache相较于cached_property,它装饰的方法是可以带参数的。
'''
class CircleLru:def __init__(self, radius):self.radius = radius@lru_cache(maxsize=128)  # 缓存最大容量def area(self, precision):'''
        如果类本身存在area属性,则此方法不生效。也就是本身属性读取和写入优先于 cached_property 方法'''
        print("计算面积")return 3.14159 * self.radius ** precisiondef test_lru_cached():print("[test_lru_cached:]")# 创建 Circle 对象circle = CircleLru(5)# 第一次访问会计算并缓存结果print(circle.radius, circle.area(precision=2))'''
    第二次访问如果输入参数相同,则直接返回缓存的结果,如果输入参数不同,则重新计算并缓存。'''
    print(circle.radius, circle.area(precision=3))print(circle.radius, circle.area(precision=3))print(circle.radius, circle.area(precision=2))print()#################################################################
class TestProperty:@propertydef test(self):print("TestProperty.test执行了")return 1def test_property():print("[test_property:]")testProperty = TestProperty()print("TestProperty.test=%s" % testProperty.test)print()#################################################################
'''
partial函数
它允许你固定一个或多个参数,从而创建一个新的函数,这个新函数在调用时只需要提供剩余的参数。
'''
# 计算一个数的幂
def power1(base, exponent1):return base ** exponent1def power2(base, exponent1, exponent2):return base ** exponent1 + exponent2def test_partial():print("[test_partial:]")square = partial(power1, exponent1=2)print(square(3))  # 输出: 9print(square(4))  # 输出: 16square = partial(power2, exponent1=2, exponent2=3)print(square(3))  # 输出: 12print(square(4))  # 输出: 19print()#################################################################
'''
partialmethod函数
它与 partial 类似,但更适合用于类方法,因为它会正确处理 self 参数。
'''
class Demo1:def __init__(self, value):self.value = valuedef get_something(self, name, age):return (self.value, name, age)# 使用 partialmethod 定义一个部分应用的方法get_something_with_default = partialmethod(get_something, name="长期", age=16)def test_partialmethod():print("[test_partialmethod:]")demo1 = Demo1(value=1)print(demo1.get_something(name=1, age=2))print(demo1.get_something_with_default())print()#################################################################
'''
@singledispatch装饰器
它用于实现函数的多态性,即根据函数的第一个参数的类型来决定调用哪个具体的实现。singledispatch 允许
你为一个函数定义多个实现,每个实现对应不同的参数类型。
'''
# 定义一个通用的函数
@singledispatch
def process(arg):return f"Processing generic argument: {arg}"# 为 int 类型定义一个特定的实现
@process.register
def _(arg: int):return f"Processing integer: {arg}"# 为 str 类型定义一个特定的实现
@process.register(str)
def _(arg):return f"Processing string1: {arg}"'''
@process.register
def _(arg: str):return f"Processing string2: {arg}"
'''
# 为 list 类型定义一个特定的实现
@process.register
def _(arg: list):return f"Processing list: {arg}"def test_singledispatch():# 调用不同类型的参数print("[test_singledispatch:]")print(process(10))  # 输出: Processing integer: 10print(process("hello"))  # 输出: Processing string: helloprint(process([1, 2, 3]))  # 输出: Processing list: [1, 2, 3]print(process(3.14))  # 输出: Processing generic argument: 3.14print()#################################################################
'''
@singledispatchmethod装饰器
它与 singledispatch 类似,但专门用于类方法(class methods)
'''
class Demo2:@singledispatchmethoddef process(self, arg):return f"Processing generic argument: {arg}"@process.registerdef _(self, arg: int):return f"Processing integer: {arg}"@process.registerdef _(self, arg: str):return f"Processing string2: {arg}"@process.register(str)def _(self, arg):return f"Processing string1: {arg}"@process.registerdef _(self, arg: list):return f"Processing list: {arg}"def test_singledispatchmethod():print("[test_singledispatchmethod:]")# 创建类的实例demo = Demo2()# 调用不同类型的参数print(demo.process(10))  # 输出: Processing integer: 10print(demo.process("hello"))  # 输出: Processing string: helloprint(demo.process([1, 2, 3]))  # 输出: Processing list: [1, 2, 3]print(demo.process(3.14))  # 输出: Processing generic argument: 3.14print()#################################################################
def my_decorator1(func):def wrapper(*args, **kwargs):print("Before function call")result = func(*args, **kwargs)print("After function call")return result# 使用 update_wrapper 更新 wrapper 的元数据update_wrapper(wrapper, func)return wrapper@my_decorator1
def my_function1():"""函数内注释内容111"""print("Inside my function")def test_update_wrapper():print("[test_update_wrapper:]")# 调用被装饰的函数my_function1()print()# 检查被装饰函数的元数据print(my_function1.__name__)  # 输出: my_functionprint(my_function1.__doc__)  # 输出: This is my function.print()#################################################################
'''
为了简化代码,functools 模块还提供了一个 wraps 装饰器,它实际上是 update_wrapper 的快捷方式。
你可以使用 wraps 装饰器来代替手动调用 update_wrapper。
'''
def my_decorator2(func):@wraps(func)def wrapper(*args, **kwargs):print("Before function call")result = func(*args, **kwargs)print("After function call")return resultreturn wrapper@my_decorator2
def my_function2():"""函数内注释内容222"""print("Inside my function")def test_wraps():print("[test_wraps:]")# 调用被装饰的函数my_function2()print()# 检查被装饰函数的元数据print(my_function2.__name__)  # 输出: my_functionprint(my_function2.__doc__)  # 输出: This is my function.print()#################################################################
'''
Functools.reduce的应用
functools.reduce函数用于对可迭代对象中的元素进行累积操作。它将一个二元函数(接受两个参数的函数)
应用于序列的所有元素,以便从左到右累积它们。
'''
def test_reduce():print("[test_reduce:]")# 使用functools.reduce计算阶乘xs = [i for i in range(1, 6)]print(xs)factorial1 = reduce(lambda x, y: x * y, xs)factorial2 = reduce(lambda x, y: x + y, xs)# 输出120,即5的阶乘print(factorial1)print(factorial2)print()#################################################################
'''
函数过滤:Functools.filterfalse的妙用
'''
def test_filterfalse():print("[test_filterfalse:]")# 使用functools.filterfalse筛选出奇数is_even = lambda x: x % 2 == 0even_numbers = []try:even_numbers = list(functools.filterfalse(is_even, range(10)))# 输出[1, 3, 5, 7, 9],即奇数print(even_numbers)except Exception as e:print(e)print()#################################################################
'''
自定义排序:Functools.cmp_to_key的魔力
functools.cmp_to_key函数用于将比较函数(接受两个参数并返回负数、零或正数
的函数)转换为关键函数,以便用于排序操作
'''
# 自定义比较函数,按长度排序
def compare_length(s1, s2):return len(s2) - len(s1)def test_cmp_to_key():print("[test_cmp_to_key:]")words = ["apple", "banana", "cherry", "date"]sorted_words = sorted(words, key=functools.cmp_to_key(compare_length))# 输出按长度排序的单词列表print(sorted_words)print()#################################################################
'''
函数调用计数:Functools.total_ordering的精妙之处
functools.total_ordering是一个装饰器,它为类定义了一些特殊方法,以便使用比较操作符(如<、<=、>、>=)进行
对象比较。可以定义自定义类,支持完整的比较操作。
'''
@functools.total_ordering
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __eq__(self, other):return self.age == other.agedef __lt__(self, other):return self.age < other.agedef test_total_ordering():print("[test_total_ordering:]")# 创建两个Person对象person1 = Person("Alice", 30)person2 = Person("Bob", 25)# 使用比较操作符进行对象比较print(person1 < person2)  # 输出Falseprint(person1 > person2)  # 输出Trueprint()if __name__ == '__main__':test_cache()test_cached_property()test_lru_cached()test_property()test_partial()test_partialmethod()test_singledispatch()test_singledispatchmethod()test_update_wrapper()test_wraps()test_reduce()test_filterfalse()test_cmp_to_key()test_total_ordering()pass

 

输出:

[test_cache:]
执行no-cache
执行cache
执行no-cache
执行no-cache[test_cached_property:]
计算面积
5 78.53975
60 78.53975[test_lru_cached:]
计算面积
5 78.53975
计算面积
5 392.69874999999996
5 392.69874999999996
5 78.53975[test_property:]
TestProperty.test执行了
TestProperty.test=1[test_partial:]
9
16
12
19[test_partialmethod:]
(1, 1, 2)
(1, '长期', 16)[test_singledispatch:]
Processing integer: 10
Processing string1: hello
Processing list: [1, 2, 3]
Processing generic argument: 3.14[test_singledispatchmethod:]
Processing integer: 10
Processing string1: hello
Processing list: [1, 2, 3]
Processing generic argument: 3.14[test_update_wrapper:]
Before function call
Inside my function
After function callmy_function1
函数内注释内容111[test_wraps:]
Before function call
Inside my function
After function callmy_function2
函数内注释内容222[test_reduce:]
[1, 2, 3, 4, 5]
120
15[test_filterfalse:]
module 'functools' has no attribute 'filterfalse'[test_cmp_to_key:]
['banana', 'cherry', 'apple', 'date'][test_total_ordering:]
False
True

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

F12调试应用:强行查看洛谷个人主页

1.前言 众所周知,洛谷的个人主页常常有些不得了的东西,但是:(洛谷估值第二名%%%)这个系统维护每次都拦着我们。 有一个比较常用的方法就是删掉域名.cn,访问外国服务器(天天炸)。所以必须要有更可靠的方法。 2.F12大法妙 这时候,我们就可以按下F12打开检查。按下左上角…

【AI+安全】看不见的AI安全威胁,揭秘隐形提示注入风险

在人工智能蓬勃发展并融合到各行各业的当前,一种新型的威胁正悄然蔓延:隐形提示注入攻击。这种看不见的攻击手段,利用了用户肉眼无法识别的特殊字符,悄无声息地影响着大语言模型的行为。它就像一个隐藏在阴影中的刺客,偷偷操纵强大的 AI 系统做出意想不到的危险行为。 如果…

unity shader 消融效果

消融效果 基础消融效果原理多方向和可控消融

React中的数据流管理

我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。本文作者:霜序前言💡 为什么数据流管理重要? React 的核心思想为:UI=render(data) ,data 就是所谓的数据,render 是 React 提供的纯函…

代码随想录算法训练营第9天 | 151.翻转字符串里的单词、右旋字符串、28. 实现 strStr()、重复的子字符串、字符串:总结篇、双指针回顾

一、刷题部分 1.1 151.翻转字符串里的单词原文链接:代码随想录 题目链接:151. 反转字符串中的单词 - 力扣(LeetCode)1.1.1 题目描述 给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。…

《CPython Internals》阅读笔记:p360-p377

《CPython Internals》学习第 20 天,p360-p377 总结,总计 18 页。 一、技术总结 1.seaborn 可视化工具。 2.dtrace (1)安装 sudo apt-get install systemtap-sdt-dev(2)编译 ./configure --with-dtrace make clean make3.snakeviz 适用于 cProfile 的可视化工具。 二、英语总…

goland2024如何安装?附安装包和激活方式

前言 大家好,我是小徐啊。goland是我们开发Go语言时的常用的开发工具,功能强大,今天,小徐就来介绍下如何安装和获取激活方式。文末附获取方式。 如何安装和激活goland 首先,我们双击下goland2024安装包,开始安装。然后,我们点击下运行按钮。然后,我们点击下一步按钮。然…

AI实现个人阅读网页插件

背景 日常工作中经常需要浏览各种Github项目或者一些网页,逐字逐句看总觉得不够效率,如果在每次打开一个新的页面时就能够掌握大概的内容,然后再决定是否深入阅读就方便多了。有了这样的念头后,总想自己开发一款简单的浏览器插件,但是始终没有提上日程。目前随着AI编程工具…

RabbitMQ之Exchange、Queue参数详解

1.先来介绍RabbitMQ中的成员Producer(生产者): 将消息发送到Exchange Exchange(交换器):将从生产者接收到的消息路由到Queue Queue(队列):存放供消费者消费的消息 BindingKey(绑定键):建立Exchange与Queue之间的关系(个人看作是一种规则,也就是Exchange将什么样的消息路由…

[日记]轻量回测框架 Backtesting.py 与 Streamlit集成

找到一个目前觉得比较轻量级的框架,结构简单易用,几行代码搞定即可搞定回测。 对于回测结果提供可视化的找到一个目前觉得比较轻量级的框架,结构简单易用,几行代码搞定即可搞定回测。 对于回测结果提供可视化的图表分析。如下图:同时提供常用的收益和风险指标数据作为量化…

【开源】Pi-hole控制面板:深入解析你的网络流量和广告拦截

今天要给大家介绍一个非常实用的开源项目——Pi-hole。这是一款基于树莓派的全能广告屏蔽助手,能够在不安装任何客户端软件的前提下为设备提供网络内容屏蔽服务,非常轻量易用。Pi-hole的主要功能: 1、 全网广告拦截: Pi-hole 充当 DNS 污水坑,阻止网络上所有设备上不需要的…

Rust多线程中安全的使用变量

在Rust语言中,一个既引人入胜又可能带来挑战的特性是闭包如何从其所在环境中捕获变量,尤其是在涉及多线程编程的情境下。 如果尝试在不使用move关键字的情况下创建新线程并传递数据至闭包内,编译器将很可能返回一系列与生命周期、借用规则及所有权相关的复杂错误信息。 不过…