PAYATHON 2026

Python Fraction 子类如何让运算返回子类实例?

数据小陈

结论

这是 Fraction 当前实现的行为。继承不会让父类的算术方法自动返回子类实例。要让 F + F 返回 F,需要在子类中重载相应运算符,并将父类的运算结果转换为子类。每种运算符都要单独处理,没有通用开关可以自动改变所有继承方法的返回类型。

为什么会返回 Fraction

示例中的 x 和 y 都是 F,但 x + y 调用的是继承来的加法实现。这个实现返回 Fraction,即使 self 是 F,结果也不会自动转换为 F。

重载运算符

可以先为加法添加子类实现:

from fractions import Fraction

class F(Fraction):
    def __add__(self, other):
        result = super().__add__(other)
        if result is NotImplemented:
            return NotImplemented
        return type(self)(result)

    def __radd__(self, other):
        result = super().__radd__(other)
        if result is NotImplemented:
            return NotImplemented
        return type(self)(result)

__add__ 处理 F 实例作为左操作数的加法,__radd__ 处理 Python 调用反向加法方法的情况。保留 NotImplemented 很重要:如果父类不支持某个操作数,应让 Python 按二元运算规则继续尝试,不要把 NotImplemented 当作可构造的结果。

这段代码只处理加法。若要让其他运算也返回 F,还需按需实现对应方法,例如减法、乘法、除法及其反向运算。不同运算的返回值未必都是数值实例:比较通常返回布尔值,整除等操作也可能返回整数。是否转换结果,应根据每种运算的语义决定。

使用时的注意点

  • type(self)(result) 假设子类构造函数能接受父类返回的结果。如果子类增加了必填参数或改变了构造规则,就需要相应调整转换逻辑。
  • 混用 F、Fraction 和其他数值类型时,结果类型取决于参与运算的类型及其运算方法。需要逐一确认要支持的操作数组合。
  • 如果需要大量自定义运算符,也可以考虑组合或包装 Fraction,但所需的数值接口需要自行提供。

备注:内容仅供参考。