重写OOP类方法致银行账户属性异常,求助问题排查
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:
- They define their own private
__account_nameand__balanceattributes before callingsuper().__init__(). In Python, double-underscore ("private") attributes are name-mangled—meaning__balanceincurrentAccountbecomes_currentAccount__balance, while the parentbankAccount's__balanceis_bankAccount__balance. These are two completely separate variables. - 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
- Switched to protected attributes: Changed
__account_name/__balanceto_account_name/_balance. Single underscores signal "protected"—child classes can safely access these attributes while still discouraging direct modification outside the class hierarchy. - Removed redundant child class initialization: Instead of redefining attributes in child
__init__, we pass custom defaults directly tosuper().__init__(), ensuring only one set of attributes exists per account instance. - Added input validation: Wrapped input conversions in
try/exceptblocks to handle non-numeric inputs gracefully (a robustness upgrade). - Fixed docstring typo: Corrected the
savingsAccountdocstring 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

