Python模块:内置模块functools函数工具详解

Python模块:内置模块functools函数工具详解
Python模块内置模块functools函数工具详解一、开篇高阶函数的工具箱functools模块提供了处理函数和可调用对象的高阶工具。从缓存优化到偏函数从包装保留到函数重载——它是写出优雅Python代码的秘密武器。⌨️ 核心功能fromfunctoolsimport(reduce,partial,lru_cache,wraps,total_ordering,singledispatch,cmp_to_key,cached_property)二、partial预填充参数的偏函数fromfunctoolsimportpartial# partial(func, *args, **kwargs) —— 固定部分参数创建新函数# 这是函数柯里化在Python中的实现# 基础用法defpower(base,exponent):returnbase**exponent squarepartial(power,exponent2)# 固定exponent2cubepartial(power,exponent3)# 固定exponent3print(square(10))# 100 —— 等价于 power(10, 2)print(cube(10))# 1000 —— 等价于 power(10, 3)# 实际应用简化回调函数deflog_event(logger,event_type,message,timestamp):记录事件日志print(f[{timestamp}]{event_type}:{message}(logger{logger}))# 为特定logger创建便利函数importtime app_logpartial(log_event,app)app_log_errorpartial(app_log,ERROR,timestamptime.time())app_log_error(数据库连接失败)# [1718000000.0] ERROR: 数据库连接失败 (loggerapp)# 应用数据处理管道deftransform(data,multiplier,offset,round_digits2):数据转换returnround(data*multiplieroffset,round_digits)# 创建专用转换函数c_to_fpartial(transform,multiplier9/5,offset32,round_digits1)f_to_cpartial(transform,multiplier5/9,offset-32*5/9,round_digits1)print(c_to_f(0))# 32.0print(c_to_f(100))# 212.0print(f_to_c(32))# 0.0三、lru_cache自动缓存函数结果fromfunctoolsimportlru_cache,cacheimporttime# lru_cache —— 最近最少使用缓存# cache —— Python 3.9无限制缓存等同于lru_cache(maxsizeNone)# 基本用法lru_cache(maxsize128)deffibonacci(n):计算斐波那契数——带缓存ifn2:returnnreturnfibonacci(n-1)fibonacci(n-2)# 第一次调用——计算并缓存starttime.perf_counter()print(fibonacci(35))print(f首次:{time.perf_counter()-start:.4f}秒)# 第二次调用——直接返回缓存starttime.perf_counter()print(fibonacci(35))print(f缓存:{time.perf_counter()-start:.6f}秒)# 查看缓存统计print(fibonacci.cache_info())# CacheInfo(hits34, misses36, maxsize128, currsize36)# 清除缓存fibonacci.cache_clear()# ⚠️ lru_cache要求参数是可哈希的# lru_cache装饰器不能用于方法会导致内存泄漏# 实际应用数据库查询缓存lru_cache(maxsize256)defget_user_by_id(user_id):模拟数据库查询print(f查询数据库: user_id{user_id})return{id:user_id,name:f用户{user_id}}print(get_user_by_id(1))# 查询数据库print(get_user_by_id(1))# 缓存命中——不查数据库四、wraps保留函数元信息fromfunctoolsimportwraps# 写装饰器时用wraps保留原函数的元信息# ❌ 没有wraps的装饰器defbad_decorator(func):defwrapper(*args,**kwargs):这是wrapper的文档returnfunc(*args,**kwargs)returnwrapperbad_decoratordefgreet(name):向用户打招呼returnfHello,{name}!print(greet.__name__)# wrapper —— 名字丢了print(greet.__doc__)# 这是wrapper的文档 —— 文档丢了# ✅ 使用wraps的装饰器defgood_decorator(func):wraps(func)defwrapper(*args,**kwargs):这是wrapper的文档returnfunc(*args,**kwargs)returnwrappergood_decoratordefgreet_v2(name):向用户打招呼returnfHello,{name}!print(greet_v2.__name__)# greet_v2 —— 正确print(greet_v2.__doc__)# 向用户打招呼 —— 正确# wraps是写装饰器的标配——不加它会导致调试困难五、其他实用工具5.1 singledispatch——函数重载fromfunctoolsimportsingledispatchsingledispatchdefformat_output(data):根据参数类型调用不同的格式化函数returnstr(data)format_output.register(list)def_(data):return[, .join(format_output(item)foritemindata)]format_output.register(dict)def_(data):items[f{k}:{format_output(v)}fork,vindata.items()]return{, .join(items)}format_output.register(int)def_(data):returnf{data:,}# 千位分隔print(format_output(1234567))# 1,234,567print(format_output([1,hello,[2,3]]))# [1, hello, [2, 3]]print(format_output({name:张三,age:25}))# {name: 张三, age: 25}5.2 cached_property——惰性属性fromfunctoolsimportcached_propertyimporttimeclassDataAnalyzer:def__init__(self,data):self.datadatacached_propertydefstatistics(self):计算统计信息——只计算一次结果被缓存print(正在计算统计数据...)time.sleep(0.5)# 模拟耗时计算return{sum:sum(self.data),avg:sum(self.data)/len(self.data),min:min(self.data),max:max(self.data),}analyzerDataAnalyzer([1,2,3,4,5])print(analyzer.statistics)# 计算打印正在计算...print(analyzer.statistics)# 缓存命中不打印# cached_property与property不同——它像实例属性一样直接访问5.3 total_ordering——自动补全比较方法fromfunctoolsimporttotal_orderingtotal_orderingclassVersion:版本号——只需定义__eq__和__lt__其余比较方法自动生成def__init__(self,major,minor,patch):self.majormajor self.minorminor self.patchpatchdef__eq__(self,other):return(self.major,self.minor,self.patch)\(other.major,other.minor,other.patch)def__lt__(self,other):return(self.major,self.minor,self.patch)\(other.major,other.minor,other.patch)def__repr__(self):returnfv{self.major}.{self.minor}.{self.patch}v1Version(1,2,3)v2Version(2,0,0)print(v1v2)# Trueprint(v1v2)# True —— 自动生成print(v1v2)# False —— 自动生成print(v1!v2)# True —— 自动生成六、总结functools是编写优雅Python函数代码的必备工具箱。从缓存优化到装饰器编写它让高阶函数编程变得简单而正确。核心工具工具一句话partial()固定参数→创建新函数lru_cache()自动缓存→加速递归和重复调用wraps()保留装饰函数的元信息cached_property惰性计算→只算一次singledispatch根据类型选择实现total_ordering补全所有比较方法✅写装饰器→用wraps慢递归→用lru_cache重复参数→用partial。