子类化pandas Timedelta重写__add__,super().__add__异常未捕获
问题排查:子类化pandas Timedelta时无法触发自定义相加分支
我来帮你理清这个问题的核心原因,以及对应的解决方案:
为什么你的代码没触发"NEW ADD"分支?
你预期super().__add__(1)会抛出TypeError,但实际上pandas的Timedelta.__add__在遇到不支持的类型时,不会抛出异常,而是返回特殊值NotImplemented。
当你执行a + 1时:
- 调用
a.__add__(1),进入你的重写方法 - 执行
super().__add__(1),父类方法无法处理int类型,返回NotImplemented,没有抛出任何异常 - 你的try-except块没有捕获到异常,所以直接跳过了"NEW ADD"分支
- 你的
__add__方法最终返回NotImplemented,Python会尝试调用右操作数的__radd__(也就是1.__radd__(a)) - 整数类型的
__radd__无法识别你的Timedelta2实例,最终抛出了那个TypeError——但这个异常已经不在你__add__方法的try块范围内了
解决方案:主动判断类型,而非依赖异常捕获
与其依赖异常捕获,不如直接先判断输入是否是整数/浮点数,提前处理这种场景,这样逻辑更清晰也更可靠:
import pandas as pd class Timedelta2(pd.Timedelta): def __add__(self, other): print("OVERRIDEN ADD") # 优先处理整数/浮点数,视为秒数 if isinstance(other, (int, float)): print("NEW ADD") return super().__add__(pd.Timedelta(seconds=other)) # 其他情况交给父类处理 print("SUPER ADD") result = super().__add__(other) # 如果父类也无法处理,返回NotImplemented让Python继续处理 return result
测试验证:
a = Timedelta2('10s') print(a + 1) # 输出 Timedelta('0 days 00:00:11') print(a + 2.5) # 输出 Timedelta('0 days 00:00:12.500000') print(a + pd.Timedelta('5s')) # 输出 Timedelta('0 days 00:00:15')
额外优化:支持右相加(比如1 + a)
如果还想支持数字在左边的相加场景(1 + a),需要同时重写__radd__方法,复用__add__的逻辑即可:
import pandas as pd class Timedelta2(pd.Timedelta): def __add__(self, other): print("OVERRIDEN ADD") if isinstance(other, (int, float)): print("NEW ADD") return super().__add__(pd.Timedelta(seconds=other)) print("SUPER ADD") return super().__add__(other) def __radd__(self, other): print("OVERRIDEN RADD") # 右相加时,数字在左侧,直接复用__add__的处理逻辑 return self.__add__(other)
测试右相加:
print(1 + a) # 输出 Timedelta('0 days 00:00:11')
内容的提问来源于stack exchange,提问作者SuperGeo
相关产品推荐
相关产品推荐

