You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python菱形继承问题:Combo类构造函数实现求助

Python菱形继承(钻石继承)构造函数实现方案

业务规则

  • Account为基类,包含核心账户属性(account_id、balance)及基础操作方法(deposit、withdraw)
  • Transaction类继承Account,扩展交易记录属性(transaction_history)及交易记录方法,不重写Account核心方法
  • Loan类继承Account,重写withdraw方法(允许超额支取至贷款限额),扩展贷款属性(loan_limit、interest_rate)
  • Combo类需多继承Transaction与Loan,整合所有类的属性,且优先使用Loan类的重写方法

类结构说明

ERD结构

  • 基表:Account(account_id[主键], balance)
  • 子表:Transaction(transaction_id[主键], account_id[外键], transaction_history)
  • 子表:Loan(loan_id[主键], account_id[外键], loan_limit, interest_rate)
  • 关联表:Combo(combo_id[主键], account_id[外键], 关联Transaction与Loan的所有字段)

UML类图

Account
       /        \
Transaction    Loan
       \        /
        Combo
  • Account:属性account_id、balance;方法__init__、deposit()、withdraw()
  • Transaction:继承Account,属性transaction_history;方法add_transaction()
  • Loan:继承Account,属性loan_limit、interest_rate;重写withdraw()
  • Combo:多继承Transaction与Loan,需整合所有属性,优先调用Loan的重写方法

现有问题代码

以下为用户提供的存在构造函数问题的代码:

class Account:
    def __init__(self, account_id, balance):
        self.account_id = account_id
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount
        return self.balance

    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount
            return self.balance
        raise ValueError("Insufficient balance")

class Transaction(Account):
    def __init__(self, account_id, balance):
        super().__init__(account_id, balance)
        self.transaction_history = []

    def add_transaction(self, amount, type):
        self.transaction_history.append({"amount": amount, "type": type})

class Loan(Account):
    def __init__(self, account_id, balance, loan_limit, interest_rate):
        super().__init__(account_id, balance)
        self.loan_limit = loan_limit
        self.interest_rate = interest_rate

    def withdraw(self, amount):
        # 重写:允许超额到贷款限额
        if amount <= self.balance + self.loan_limit:
            self.balance -= amount
            return self.balance
        raise ValueError("Exceeds loan limit")

# 问题:Combo类无法正确初始化所有属性,且无法优先调用Loan的重写方法
class Combo(Transaction, Loan):
    pass

解决方案

核心思路

  1. 调整继承顺序:将Combo的继承顺序改为Combo(Loan, Transaction),利用Python的MRO(方法解析顺序)优先调用Loan的重写方法
  2. 构造函数整合属性:通过super()初始化Loan与Account的属性,手动初始化Transaction的扩展属性(或通过super()链式调用)

修正后的完整代码

class Account:
    def __init__(self, account_id, balance):
        self.account_id = account_id
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount
        return self.balance

    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount
            return self.balance
        raise ValueError("Insufficient balance")

class Transaction(Account):
    def __init__(self, account_id, balance):
        super().__init__(account_id, balance)
        self.transaction_history = []

    def add_transaction(self, amount, type):
        self.transaction_history.append({"amount": amount, "type": type})

class Loan(Account):
    def __init__(self, account_id, balance, loan_limit, interest_rate):
        super().__init__(account_id, balance)
        self.loan_limit = loan_limit
        self.interest_rate = interest_rate

    def withdraw(self, amount):
        if amount <= self.balance + self.loan_limit:
            self.balance -= amount
            return self.balance
        raise ValueError("Exceeds loan limit")

# 修正后的Combo类
class Combo(Loan, Transaction):
    def __init__(self, account_id, balance, loan_limit, interest_rate):
        # 初始化Loan及Account的属性
        super().__init__(account_id, balance, loan_limit, interest_rate)
        # 初始化Transaction的扩展属性(因Transaction的__init__仅依赖Account,可直接初始化)
        self.transaction_history = []

    # 无需重写withdraw,MRO会优先调用Loan的版本

测试用例

def test_combo_account():
    # 初始化Combo实例,包含所有属性
    combo_acc = Combo("COMBO_001", 1000, 5000, 0.05)
    
    # 验证所有属性是否正确初始化
    assert combo_acc.account_id == "COMBO_001"
    assert combo_acc.balance == 1000
    assert combo_acc.loan_limit == 5000
    assert combo_acc.interest_rate == 0.05
    assert combo_acc.transaction_history == []
    
    # 测试Loan的重写withdraw方法(允许超额支取)
    combo_acc.withdraw(1500)
    assert combo_acc.balance == -500  # 1000-1500=-500,未超过1000+5000=6000的限额
    
    # 测试Transaction的add_transaction方法
    combo_acc.add_transaction(1500, "withdraw")
    assert len(combo_acc.transaction_history) == 1
    assert combo_acc.transaction_history[0]["amount"] == 1500
    
    # 测试继承自Account的deposit方法
    combo_acc.deposit(2000)
    assert combo_acc.balance == 1500
    
    # 测试超出贷款限额的支取
    try:
        combo_acc.withdraw(7000)
        assert False, "未抛出超出限额异常"
    except ValueError as e:
        assert str(e) == "Exceeds loan limit"
    
    print("所有测试用例执行通过")

test_combo_account()

内容的提问来源于stack exchange,提问作者Harley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:17:54