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

重写OOP类方法致银行账户属性异常,求助问题排查

Fixing Persistent Balance Issues in Your Python OOP Bank Account Code

Let's break down why your balance isn't updating correctly between deposits and withdrawals, and fix the code step by step:

The Root Problem

Your child classes (currentAccount and savingsAccount) are making two critical mistakes in their __init__ methods:

  1. They define their own private __account_name and __balance attributes before calling super().__init__(). In Python, double-underscore ("private") attributes are name-mangled—meaning __balance in currentAccount becomes _currentAccount__balance, while the parent bankAccount's __balance is _bankAccount__balance. These are two completely separate variables.
  2. When you call super().__init__() without passing arguments, it initializes the parent's attributes to default values (account_name="Bank Account", balance=1500)—creating conflicting, unlinked state between parent and child.

So when you run savingsObject.deposit(value), you're modifying _savingsAccount__balance, but savingsObject.withdraw(value) uses the parent's method which edits _bankAccount__balance. That's why your balance seems to reset—you're working with two separate balances!

The Fixed Code

Here's the adjusted code with consistent balance tracking:

class bankAccount():
    '''This is a bank account class'''
    def __init__(self, account_name = "Bank Account", balance = 1500):
        # Use single underscore for protected attributes (accessible to child classes)
        self._account_name = account_name
        self._balance = balance

    def deposit(self, value):
        self._balance += value
        print("You now have: ", self._balance)

    def withdraw(self, value):
        self._balance -= value
        print("You now have: ", self._balance)

class currentAccount(bankAccount):
    '''This is a current account class'''
    def __init__(self, account_name = "Current Account", balance = 1500):
        # Pass custom values to parent constructor instead of redefining attributes
        super().__init__(account_name, balance)

    def withdraw(self, value):
        if value > 1000:
            print("You will have to phone the bank manager")
        else:
            self._balance -= value
            print("You now have: ", self._balance)

class savingsAccount(bankAccount):
    '''This is a savings account class'''  # Fixed docstring typo
    def __init__(self, account_name = "Savings Account", balance = 1500):
        # Pass custom values to parent constructor
        super().__init__(account_name, balance)

    def deposit(self, value):
        # Use the shared _balance attribute
        self._balance += (value * 1.03)
        print("You now have: ", self._balance)

currentObject = currentAccount()
savingsObject = savingsAccount()

while True:
    print("1. Current Account")
    print("2. Savings Account")
    try:
        menu_option = int(input())
    except ValueError:
        print("Please enter a valid number!")
        continue
        
    if menu_option == 1:
        print("1. Deposit funds")
        print("2. Withdraw funds")
        try:
            submenu_option = int(input())
        except ValueError:
            print("Please enter a valid number!")
            continue
            
        if submenu_option == 1:
            try:
                value = int(input("How much would you like to deposit? "))
                currentObject.deposit(value)
            except ValueError:
                print("Please enter a valid amount!")
        elif submenu_option == 2:
            try:
                value = int(input("How much would you like to withdraw? "))
                currentObject.withdraw(value)
            except ValueError:
                print("Please enter a valid amount!")
        else:
            print("Wrong menu choice!")
    elif menu_option == 2:
        print("1. Deposit funds")
        print("2. Withdraw funds")
        try:
            submenu_option = int(input())
        except ValueError:
            print("Please enter a valid number!")
            continue
            
        if submenu_option == 1:
            try:
                value = int(input("How much would you like to deposit? "))
                savingsObject.deposit(value)
            except ValueError:
                print("Please enter a valid amount!")
        elif submenu_option == 2:
            try:
                value = int(input("How much would you like to withdraw? "))
                savingsObject.withdraw(value)
            except ValueError:
                print("Please enter a valid amount!")
        else:
            print("Wrong menu choice!")
    else:
        print("Wrong menu choice!")
input()

Key Changes Explained

  1. Switched to protected attributes: Changed __account_name/__balance to _account_name/_balance. Single underscores signal "protected"—child classes can safely access these attributes while still discouraging direct modification outside the class hierarchy.
  2. Removed redundant child class initialization: Instead of redefining attributes in child __init__, we pass custom defaults directly to super().__init__(), ensuring only one set of attributes exists per account instance.
  3. Added input validation: Wrapped input conversions in try/except blocks to handle non-numeric inputs gracefully (a robustness upgrade).
  4. Fixed docstring typo: Corrected the savingsAccount docstring to match its purpose.

Now deposits and withdrawals will modify the same balance, so your account state stays consistent across operations.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:16:14