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

Python多层继承报错:'CheckingAccount'对象无'balance'属性

解决多层继承中'CheckingAccount' object has no attribute 'balance'的问题

嘿,我看到你在多层继承的Python项目里遇到了属性找不到的问题,咱们来一步步拆解问题出在哪:

核心问题分析

你遇到的AttributeError本质是子类CheckingAccount和SavingAccount没有正确初始化父类BankAccount的属性。你的子类构造函数里只是把传入的对象存在self.bankAccount里,完全没有调用父类的__init__方法,导致balance、accountNumber这些父类属性根本没被创建,自然访问不到。

另外还有两个隐藏问题:

  • BankAccount里的accountNumber是类属性,在类定义时就生成了,这意味着所有BankAccount实例都会共用同一个账号,这显然不符合实际需求。
  • BankAccount的__init__接收customer参数,但你的子类在实例化时直接传了Customer对象,却没正确对接父类的构造逻辑。

修正后的代码

下面是修复好的完整代码,我会标注关键修改点:

from random import randint  # 把导入放到文件顶部,避免重复导入

class Customer:
    def __init__(self, firstName, lastName, social):
        self.firstName = firstName
        self.lastName = lastName
        self.social = social

    def setfirstName(self, firstName):
        self.firstName = firstName

    def setlastName(self, lastName):
        self.lastName = lastName

    def __str__(self):
        # 不要在__str__里修改实例属性self.name,直接返回字符串即可
        return "{}, {} (SSN:{})".format(self.firstName, self.lastName, self.social)

class BankAccount(Customer):
    def __init__(self, customer, balance=0):
        # 调用父类Customer的构造函数,初始化Customer的属性
        super().__init__(customer.firstName, customer.lastName, customer.social)
        # 把accountNumber改成实例属性,每个账号生成唯一值
        n = 10
        range_start = 10 ** (n - 1)
        range_end = (10 ** n) - 1
        self.accountNumber = randint(range_start, range_end)
        self.balance = balance

    def setCustomer(self, customer):
        self.firstName = customer.firstName
        self.lastName = customer.lastName
        self.social = customer.social

    def getCustomer(self):
        # 不需要传参数,直接返回实例自身的Customer属性
        return (self.firstName, self.lastName, self.social)

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

    def withdrawal(self, amount):
        self.balance -= amount
        return self.balance

    def __str__(self):
        return "{} account number: {}, balance: ${:.2f}".format(
            super().__str__(), self.accountNumber, self.balance
        )

class CheckingAccount(BankAccount):
    def __init__(self, customer, balance=0):
        # 调用父类BankAccount的构造函数,初始化balance等属性
        super().__init__(customer, balance)

    def applyAnnualInterest(self):
        excess = self.balance - 10000
        if excess > 0:
            self.balance += excess * 0.02
        return self.balance

class SavingAccount(BankAccount):
    def __init__(self, customer, balance=0):
        # 同样调用父类构造函数
        super().__init__(customer, balance)

    def applyAnnualInterest(self):
        self.balance += self.balance * 0.05
        return self.balance

def main():
    alin = Customer('Alin', 'Smith', '111-11-1111')
    mary = Customer('Mary', 'Lee', '222-22-2222')
    # 实例化子类时,直接传Customer对象和初始余额(可选)
    alinAccnt = CheckingAccount(alin, 0)
    maryAccnt = SavingAccount(mary, 0)
    alinAccnt.deposit(20000)
    alinAccnt.applyAnnualInterest()  # 可以测试利息计算
    print(alinAccnt)

if __name__ == "__main__":
    main()

关键修改说明

  1. 修复子类构造函数:
    • 用super().__init__(...)调用父类的构造函数,让子类继承父类的所有属性(比如balance、accountNumber),而不是把父类对象存成一个属性。
  2. 修正accountNumber为实例属性:
    • 把账号生成逻辑放到BankAccount的__init__里,确保每个银行账号实例都有唯一的账号。
  3. 优化Customer的__str__方法:
    • 不要在__str__中修改实例属性,直接返回格式化后的字符串即可,避免不必要的副作用。
  4. 调整BankAccount的setCustomer和getCustomer方法:
    • 因为BankAccount继承自Customer,所以直接操作自身的firstName等属性即可,不需要额外存self.customer对象。

现在运行代码,你会发现balance属性能正常访问,存款、利息计算也都能正常工作了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:27:52