Python Functools模块
代码:
#coding=utf-8 import 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 n def 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_property def area(self): ''' 如果类本身存在area属性,则此方法不生效。也就是本身属性读取和 写入优先于 cached_property 方法 ''' print("计算面积") return 3.14159 * self.radius ** 2 def test_cached_property(): print("[test_cached_property:]") # 创建 Circle 对象 circle = CircleCache(5) # 第一次访问 area 属性时会计算并缓存结果 print(circle.radius, circle.area) del circle.radius circle.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 ** precision def 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: @property def test(self): print("TestProperty.test执行了") return 1 def test_property(): print("[test_property:]") testProperty = TestProperty() print("TestProperty.test=%s" % testProperty.test) print() ################################################################# ''' partial函数 它允许你固定一个或多个参数,从而创建一个新的函数,这个新函数在调用时只需要提供剩余的参数。 ''' # 计算一个数的幂 def power1(base, exponent1): return base ** exponent1 def power2(base, exponent1, exponent2): return base ** exponent1 + exponent2 def test_partial(): print("[test_partial:]") square = partial(power1, exponent1=2) print(square(3)) # 输出: 9 print(square(4)) # 输出: 16 square = partial(power2, exponent1=2, exponent2=3) print(square(3)) # 输出: 12 print(square(4)) # 输出: 19 print() ################################################################# ''' partialmethod函数 它与 partial 类似,但更适合用于类方法,因为它会正确处理 self 参数。 ''' class Demo1: def __init__(self, value): self.value = value def 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: 10 print(process("hello")) # 输出: Processing string: hello print(process([1, 2, 3])) # 输出: Processing list: [1, 2, 3] print(process(3.14)) # 输出: Processing generic argument: 3.14 print() ################################################################# ''' @singledispatchmethod装饰器 它与 singledispatch 类似,但专门用于类方法(class methods) ''' class Demo2: @singledispatchmethod def process(self, arg): return f"Processing generic argument: {arg}" @process.register def _(self, arg: int): return f"Processing integer: {arg}" @process.register def _(self, arg: str): return f"Processing string2: {arg}" @process.register(str) def _(self, arg): return f"Processing string1: {arg}" @process.register def _(self, arg: list): return f"Processing list: {arg}" def test_singledispatchmethod(): print("[test_singledispatchmethod:]") # 创建类的实例 demo = Demo2() # 调用不同类型的参数 print(demo.process(10)) # 输出: Processing integer: 10 print(demo.process("hello")) # 输出: Processing string: hello print(demo.process([1, 2, 3])) # 输出: Processing list: [1, 2, 3] print(demo.process(3.14)) # 输出: Processing generic argument: 3.14 print() ################################################################# 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_function print(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 result return 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_function print(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 == 0 even_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 = name self.age = age def __eq__(self, other): return self.age == other.age def __lt__(self, other): return self.age < other.age def test_total_ordering(): print("[test_total_ordering:]") # 创建两个Person对象 person1 = Person("Alice", 30) person2 = Person("Bob", 25) # 使用比较操作符进行对象比较 print(person1 < person2) # 输出False print(person1 > person2) # 输出True print() 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 call my_function1 函数内注释内容111 [test_wraps:] Before function call Inside my function After function call my_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
本文来自博客园,作者:河北大学-徐小波,转载请注明原文链接:https://www.cnblogs.com/xuxiaobo/p/18691849

【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步