要实现的目标,简单示例:
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(<function date_trunc at 0x000002538E45E5E0>, '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))输出:
到此这篇关于python 嵌套型partials的使用的文章就介绍到这了,更多相关python 嵌套型内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
查看更多关于python 嵌套型partials的使用的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did99098