Python中如何为datetime对象创建扩展方法及替代方案
Python 无法直接给内置的datetime.datetime类添加可通过实例直接调用的自定义扩展方法。datetime属于C层实现的内置扩展类型,解释器不允许直接修改这类类型的属性,如果你尝试直接给类绑定方法,运行时会直接抛出TypeError: can't set attributes of built-in/extension type 'datetime.datetime'。
按照适配需求的优先级排序:
方案1:自定义datetime子类(最贴合
date.my_extension()调用习惯)
自定义子类继承原生datetime.datetime,把所有自定义处理逻辑写在子类中,子类完全兼容原生datetime的所有属性、方法,调用形式和预期完全一致。
示例代码:import datetime class CustomDatetime(datetime.datetime): def my_extension(self, date_fmt="%Y%m%d"): # 这里写自定义逻辑,比如格式化输出、计算工作日、推算N天后的日期都可以 return self.strftime(date_fmt) # 实例化时使用自定义子类即可 date = CustomDatetime(2022, 2, 2) # 直接点调用自定义方法 print(date.my_extension()) # 输出 20220202 print(date.my_extension("%Y年%m月%d日")) # 输出 2022年02月02日 # 原生datetime的方法、属性完全不受影响 print(date.year, date.month) # 输出 2022 2这个方案的唯一缺点是:如果你的日期实例是其他库返回的原生datetime对象,需要手动做一次类型转换才能调用自定义方法,转换成本很低,通过
CustomDatetime.fromtimestamp(origin_dt.timestamp(), origin_dt.tzinfo)即可完成转换。方案2:独立工具函数(最稳妥无侵入,生产环境首选)
如果不想做类型封装,最通用、没有任何兼容风险的方案是写独立的工具函数,把datetime实例作为第一个参数传入即可。
示例代码:import datetime def dt_my_extension(dt: datetime.datetime, date_fmt="%Y%m%d"): return dt.strftime(date_fmt) date = datetime.datetime(2022, 2, 2) print(dt_my_extension(date)) # 输出 20220202这个方案的缺点是调用形式不是实例点方法的形式,但胜在完全不侵入原生类型,不管日期实例来自哪里,只要是标准datetime类型就能直接传参使用,不会和任何第三方库产生冲突。
方案3:内置类猴子补丁(极度不推荐生产使用)
借助第三方库可以强行给内置datetime类绑定自定义方法,实现点调用效果,但这种方案会全局修改内置类型的行为,很容易和其他第三方库的逻辑产生命名冲突、行为异常,只适合个人临时写小脚本用,绝对不要在生产项目、多人协作项目里用。
示例仅作了解:# 需先安装第三方库 forbiddenfruit from forbiddenfruit import curse import datetime def my_extension(self, date_fmt="%Y%m%d"): return self.strftime(date_fmt) # 强行给内置datetime类绑定方法 curse(datetime.datetime, "my_extension", my_extension) date = datetime.datetime(2022, 2, 2) print(date.my_extension()) # 可以正常调用
内容的提问来源于stack exchange,提问作者Jason

