要实现的目标,简单示例:
from functools import partial def func1(f): return f def func2(f1): return f1 def func(n): return n p = partial(func2, partial(func1, partial(func, 5))) print(p()()()) # 输出5
简化嵌套式的partial对象p,不要调用三次
p() # 输出5
可以到最后的看解决方法
场景:
为了实现一个通用性较高的sql生成方法,我写了一个通用的转换时间格式的方法,简略版大概如下:
def date_trunc(time_unit: str, field): return f"date_trunc("{time_unit}", `{field}`)" print(date_trunc("WEEK", "event_date")) print(date_trunc("DAY", "event_date")) ...
实际就是sql
中的date_trunc
方法
输出:
date_trunc("WEEK", `event_date`)
date_trunc("DAY", `event_date`)
由于校验日期参数和日期截断是前后挨着执行的
我把上面的几个方法写进了一个Enum
对象TimeFormatter
使用partial将date_trunc方法包起来以充当Enum的成员,实现用Enum类校验日期参数,用Enum
类成员的date_trunc方法执行日期截断
这样在校验完日期参数后立马调用它本身的date_trunc方法执行日期截断:执行日期截断date_trunc
方法时需要传入参数time_unit
,也就是"DAY", “WEEK
”, "MONTH
"等字符串
from enum import Enum from functools import partial def date_trunc(time_unit: str, field): # 注意这里的date_trunc和上面简略版举例的有所不同,需要两个参数 return f"date_trunc("{time_unit}", `{field}`)" class TimeFormatter(Enum): DAY = partial(date_trunc, "DAY") WEEK = partial(date_trunc, "WEEK") MONTH = partial(date_trunc, "MONTH") def __call__(self, *args, **kwargs): return self.value(*args, **kwargs)
这里的call方法让Enum
对象TimeFormatter
的成员变得可以被调用(callable),关于Enum的一些用法可以参考我上期的文章
到这里我依然可以正常调用我的date_trunc方法
field = "event_time" tf_wk = TimeFormatter.__getattr__("WEEK") # 先校验格式 print(tf_wk(field)) # 传入相应的field对象就会执行对应的date_trunc方法截断时间 tf_day = TimeFormatter.__getattr__("DAY") # 校验格式 print(tf_day(field)) # 执行date_trunc
输出:
date_trunc("WEEK", `event_time`)
date_trunc("DAY", `event_time`)
直到我想要使用二次的时间格式转换时,也就是在date_trunc之后再执行一个from_timestamp将sql中的日期对象event_time转换为指定的"yyyy-MM-dd"格式
from_timestamp(date_trunc("DAY", `event_time`), "yyyy-MM-dd")
发现好像没那么顺利地执行时间格式转换:
from enum import Enum from functools import partial def from_timestamp(field, time_fmt: str): return f"from_timestamp(`{field}`, "{time_fmt}")" class TimeFormatter(Enum): HOUR = partial(from_timestamp, partial(date_trunc, "HOUR")) def __call__(self, *args, **kwargs): return self.value(*args, **kwargs) tf_hour = TimeFormatter.__getattr__("HOUR") print(tf_hour("event_hour"))
输出:
from_timestamp(`functools.partial(
, "HOUR")`, "event_hour")
不是想要的结果
查了一些解决办法,有循环调用,有用组合函数(function composition)的,
最后发现可以用一个简单的方法解决:
from enum import Enum from functools import partial def date_trunc(time_unit: str, field): return f"date_trunc("{time_unit}", `{field}`)" def from_timestamp(field, time_fmt: str): return f"from_timestamp(`{field}`, "{time_fmt}")" def fts(time_fmt, time_unit, field): return from_timestamp(date_trunc(time_unit, field), time_fmt) class TimeFormatter2(Enum): month = partial(fts, "yyyy-MM", "month") def __call__(self, *args, **kwargs): return self.value(*args, **kwargs)
输出:
from_timestamp(`date_trunc("month", `acmonth`)`, "yyyy-MM")
焯!原来只要多写一个函数就可以了!
前面简单示例的解决方法:
def nested_partials(f2, f1, n): return f2(f1(n)) p = partial(nested_partials, func2, func1) print(p(5))
输出:
5
到此这篇关于python 嵌套型partials的使用的文章就介绍到这了,更多相关python 嵌套型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
X 关闭
X 关闭
- 15G资费不大降!三大运营商谁提供的5G网速最快?中国信通院给出答案
- 2联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 3亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 4现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 5如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 6AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 7转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 8充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 9好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 10名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?