Pythonfunctools深度应用 Python functools 深度应用functools 提供高阶函数工具, 用于函数式编程、缓存、分发和装饰器。1. lru_cache — 最近最少使用缓存-----------------------------------from functools import lru_cacheimport time# maxsize 设置缓存容量, typedTrue 区分不同类型参数lru_cache(maxsize128, typedTrue)def fibonacci(n):递归斐波那契, 使用缓存避免重复计算if n 2:return nreturn fibonacci(n - 1) fibonacci(n - 2)start time.perf_counter()print(fibonacci(35):, fibonacci(35))print(计算耗时:, time.perf_counter() - start) # 极快, 因为有缓存print(缓存信息:, fibonacci.cache_info()) # CacheInfo(hits..., misses..., ...)# cache_info() 返回命中/未命中/最大/当前大小# 查看和清除缓存print(缓存参数:, fibonacci.cache_parameters()) # {maxsize: 128, typed: True}fibonacci.cache_clear() # 清空缓存# typedTrue 时, 1 和 1.0 被视为不同参数lru_cache(typedTrue)def multiply(a, b):return a * bmultiply(1, 2)multiply(1.0, 2)print(typed 区分 int/float:, multiply.cache_info().misses) # 2 次未命中2. cache (Python 3.9) — 无大小限制的缓存--------------------------------------------from functools import cachecachedef expensive_compute(n):等价于 lru_cache(maxsizeNone), 内存允许时无限缓存print(f 计算 {n}...)return sum(range(n))print(首次调用:, expensive_compute(10_000_000)) # 实际计算print(缓存调用:, expensive_compute(10_000_000)) # 直接从缓存返回3. cached_property — 惰性计算属性------------------------------------from functools import cached_propertyimport mathclass Circle:def __init__(self, radius):self.radius radiuscached_propertydef area(self):首次访问时计算并缓存, 后续直接返回缓存值print( 计算面积...)return math.pi * self.radius ** 2cached_propertydef circumference(self):print( 计算周长...)return 2 * math.pi * self.radiusc Circle(5)print(面积:, c.area) # 触发计算print(面积:, c.area) # 直接从缓存读取, 不重复计算print(周长:, c.circumference) # 触发计算# cached_property 在对象生命周期内有效, 修改 radius 不会自动更新c.radius 10print(修改后面积(缓存旧值):, c.area) # 仍是之前的结果# 删除属性可清除缓存, 下次访问重新计算del c.areaprint(清除后面积:, c.area) # 重新计算4. singledispatch — 单参数类型分发---------------------------------------from functools import singledispatchsingledispatchdef serialize(obj):默认序列化函数, 抛出类型错误raise TypeError(f不支持的类型: {type(obj)})# 为特定类型注册实现serialize.register(int)def _(obj):return fint:{obj}serialize.register(str)def _(obj):return fstr:{obj}serialize.register(list)serialize.register(tuple) # 多个类型注册同一个实现def _(obj):items , .join(serialize(item) for item in obj)return flist:[{items}]serialize.register(dict)def _(obj):pairs , .join(f{k}: {serialize(v)} for k, v in obj.items())return fdict:{{{pairs}}}# 注册 None 类型的处理serialize.register(type(None))def _(obj):return nullprint(serialize(42)) # int:42print(serialize(hello)) # str:helloprint(serialize([1, a, None])) # list:[int:1, str:a, null]print(serialize({x: 10})) # dict:{x: int:10}# 查看所有注册类型print(已注册的类型:, serialize.registry)5. singledispatchmethod — 方法级别类型分发---------------------------------------------from functools import singledispatchmethodclass Processor:singledispatchmethoddef process(self, arg):默认处理方法raise NotImplementedError(f未支持类型: {type(arg)})process.register(int)def _(self, arg):return f处理整数: {arg * 2}process.register(str)def _(self, arg):return f处理字符串: {arg.upper()}process.register(list)def _(self, arg):return [self.process(item) for item in arg]p Processor()print(p.process(5)) # 处理整数: 10print(p.process(hello)) # 处理字符串: HELLOprint(p.process([1, a])) # 递归处理列表6. partial / partialmethod — 偏函数---------------------------------------from functools import partial, partialmethodimport os# partial: 固定函数的部分参数def power(base, exponent):return base ** exponentsquare partial(power, exponent2) # 固定 exponent2cube partial(power, exponent3) # 固定 exponent3print(平方:, square(5)) # 25print(立方:, cube(5)) # 125# 实际应用: 读取文件时指定编码read_utf8 partial(open, encodingutf-8, moder)# 用 read_utf8(file.txt) 代替 open(file.txt, encodingutf-8, moder)# partialmethod: 用于类方法class Cell:def __init__(self):self._alive Falsedef set_state(self, state):self._alive stateset_alive partialmethod(set_state, True)set_dead partialmethod(set_state, False)cell Cell()cell.set_alive() # 等价于 cell.set_state(True)print(细胞存活:, cell._alive)7. reduce — 累积归约------------------------from functools import reduce# reduce 将二元函数累积应用到序列上numbers [1, 2, 3, 4, 5]product reduce(lambda a, b: a * b, numbers)print(累乘结果:, product) # 120# reduce 支持初始值, 为空序列时返回初始值sum_with_init reduce(lambda a, b: a b, [], 0)print(空序列归约:, sum_with_init) # 0# 实战: 扁平化嵌套列表nested [[1, 2], [3, 4], [5]]flat reduce(lambda acc, x: acc x, nested, [])print(展平嵌套列表:, flat) # [1, 2, 3, 4, 5]8. wraps — 装饰器保留元数据-------------------------------from functools import wrapsdef log_calls(func):wraps(func) # 保留原函数的 __name__, __doc__, __module__ 等def wrapper(*args, **kwargs):print(f调用函数: {func.__name__})return func(*args, **kwargs)return wrapperlog_callsdef greet(name):向指定用户问好return f你好, {name}!print(greet(小明)) # 输出调用日志及问候print(函数名:, greet.__name__) # greet (没有 wraps 会变成 wrapper)print(文档:, greet.__doc__.strip()) # 向指定用户问好9. total_ordering — 自动补全比较方法----------------------------------------from functools import total_orderingtotal_orderingclass Version:只需定义 __eq__ 和 __lt__, 其余比较操作自动生成def __init__(self, major, minor):self.major majorself.minor minordef __eq__(self, other):return (self.major, self.minor) (other.major, other.minor)def __lt__(self, other):return (self.major, self.minor) (other.major, other.minor)v1 Version(2, 0)v2 Version(3, 1)print(v1 v2:, v1 v2) # Trueprint(v1 v2:, v1 v2) # True (由 __lt__ 和 __eq__ 推导)print(v1 v2:, v1 v2) # Falseprint(v1 v2:, v1 v2) # False10. cmp_to_key — 旧式比较转键函数------------------------------------from functools import cmp_to_keydef custom_cmp(a, b):自定义比较逻辑: 按长度优先, 同长按字母序if len(a) ! len(b):return len(b) - len(a) # 长度降序return -1 if a b else (1 if a b else 0) # 字母升序strings [banana, apple, cherry, date, elderberry]sorted_strings sorted(strings, keycmp_to_key(custom_cmp))print(自定义排序:, sorted_strings)# [elderberry, banana, cherry, apple, date]总结: functools 可优化性能(缓存)、提高复用(偏函数)、增强可读性(类型分发), 是高级 Python 编程的基石.