Python | 运算符重载

介绍

要让自定义类支持 | 运算,需要在类中实现 __or__ 方法

如果还想支持 反向运算,比如 3 | 自定义对象,还需要实现 __ror__

方法说明

  • __or__(self, other):定义 self | other 的行为

  • __ror__(self, other):定义 other | self 的行为(当 other 不支持 | self 时触发)

案例

假设我们有一个 购物车类,想通过 | 运算符实现 两个购物车的水果合并(合并规则:保留所有水果,数量取两者中的最大值),这比位或的原生含义更贴合日常认知。

定义类

class FruitCart:
    """水果购物车类"""
    def __init__(self, fruits=None):
        # 初始化购物车,默认空字典(水果名: 数量)
        self.fruits = fruits if fruits is not None else {}

    def __repr__(self):
        # 自定义打印格式,方便查看结果
        return f"购物车:{self.fruits}"

    # 核心:自定义 | 运算符,实现两个购物车合并
    def __or__(self, other):
        # 第一步:检查右侧是否也是 FruitCart 实例(类型校验)
        if not isinstance(other, FruitCart):
            raise TypeError("| 运算符右侧必须是 FruitCart 实例!")

        # 第二步:创建新购物车,用于存储合并结果
        merged_fruits = {}

        # 第三步:合并当前购物车的水果
        for fruit, count in self.fruits.items():
            merged_fruits[fruit] = count

        # 第四步:合并另一个购物车的水果(数量取最大值)
        for fruit, count in other.fruits.items():
            if fruit in merged_fruits:
                # 如果水果已存在,数量取两者中更大的
                merged_fruits[fruit] = max(merged_fruits[fruit], count)
            else:
                # 水果不存在,直接添加
                merged_fruits[fruit] = count

        # 第五步:返回新的合并后购物车
        return FruitCart(merged_fruits)

执行

# 测试自定义 | 运算符
if __name__ == "__main__":
    # 创建两个购物车
    cart1 = FruitCart({"苹果": 2, "香蕉": 3})
    cart2 = FruitCart({"香蕉": 5, "橙子": 4})

    # 使用 | 运算符合并购物车(核心:触发 __or__ 方法)
    merged_cart = cart1 | cart2

    # 打印结果
    print("购物车1:", cart1)
    print("购物车2:", cart2)
    print("合并后:", merged_cart)

运行结果

购物车1: 购物车:{'苹果': 2, '香蕉': 3}
购物车2: 购物车:{'香蕉': 5, '橙子': 4}
合并后: 购物车:{'苹果': 2, '香蕉': 5, '橙子': 4}

代码逐行解释

  1. 类初始化 __init__:接收一个水果字典(键:水果名,值:数量),默认空字典,方便创建空购物车;
  2. 打印格式 __repr__:自定义打印时的显示效果,避免输出默认的内存地址,更直观;
  3. 核心方法 __or__:
    • 先校验右侧对象类型,避免和非购物车对象错误运算;
    • 创建新字典存储合并结果,保证原购物车不被修改(符合 Python 不可变设计的直觉);
    • 先把第一个购物车的水果加入新字典;
    • 遍历第二个购物车的水果:已存在的水果取数量最大值,不存在的直接添加;
    • 返回新的 FruitCart 实例,作为合并结果。

案例拓展:支持多购物车连续合并

因为 __or__ 返回的是 FruitCart 实例,所以可以像 cart1 | cart2 | cart3 这样连续合并:

# 新增第三个购物车
cart3 = FruitCart({"橙子": 2, "葡萄": 1})

# 连续合并
total_cart = cart1 | cart2 | cart3
print("连续合并后:", total_cart)
# 输出:连续合并后:购物车:{'苹果': 2, '香蕉': 5, '橙子': 4, '葡萄': 1}

注意事项

  1. 语义合理性:重载运算符时要符合直觉,比如 | 通常用于「管道/合并」类逻辑,不要滥用(比如用 | 做减法);
  2. 类型检查:一定要在 __or__ 中检查 other 的类型,避免和其他类型错误运算;
  3. 返回值:可以返回新实例、可调用对象(如示例中的 Chain),根据需求设计。

总结

  1. Python 支持通过实现 __or__ 魔法方法自定义 | 运算符的行为,这是运算符重载的核心;
  2. 自定义时建议做好类型检查,保证运算符语义符合直觉(如管道、合并);

原文出处:/show_1GW2qDV2kDsh.html