代码:
#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