Your personal teaching assistant
Higher quality grading in a fraction of the time
View
student submission · bank_account.py
1class BankAccount:
2 def __init__(self, owner, account_number, balance=0.0):
3 if not owner:
4 raise ValueError("owner name required")
5 if balance < 0:
6 raise ValueError("initial balance cannot be negative")
7 self.owner = owner
8 self.account_number = account_number
9 self.balance = round(balance, 2)
10 self.transactions = []
11
12 def deposit(self, amount):
13 if amount <= 0:
14 raise ValueError("deposit amount must be positive")
15 self.balance = round(self.balance + amount, 2)
16 self.transactions.append(("deposit", amount, self.balance))
17
18 def withdraw(self, amount):
19 if amount <= 0:
20 raise ValueError("withdrawal amount must be positive")
21 if amount > self.balance:
22 raise ValueError("insufficient funds")
23 self.balance = round(self.balance - amount, 2)
24 self.transactions.append(("withdrawal", amount, self.balance))
25
26 def transfer(self, amount, target):
27 if amount <= 0:
28 raise ValueError("transfer amount must be positive")
29 if amount > self.balance:
30 raise ValueError("insufficient funds")
31 self.balance = round(self.balance - amount, 2)
32 target.balance = round(target.balance + amount, 2)
33 self.transactions.append(("transfer_out", amount, self.balance))
34 target.transactions.append(("transfer_in", amount, target.balance))
35
36 def get_balance(self):
37 return self.balance
38
39 def get_statement(self):
40 lines = [f"Account: {self.account_number} ({self.owner})", "-" * 50]
41 for t_type, amount, bal in self.transactions:
42 lines.append(f" {t_type:<16} ${amount:>8.2f} bal: ${bal:.2f}")
43 lines.append("-" * 50)
44 lines.append(f" Current balance: ${self.balance:.2f}")
45 return "\n".join(lines)
46
47
48def main():
49 alice = BankAccount("Alice", "ACC-001", 500.0)
50 bob = BankAccount("Bob", "ACC-002", 200.0)
51
52 alice.deposit(150.0)
53 alice.withdraw(75.0)
54 alice.transfer(100.0, bob)
55
56 print(alice.get_statement())
57 print()
58 print(bob.get_statement())
59
60
61if __name__ == "__main__":
62 main()
63Overall feedback
Core operations and balance tracking are correct, but validation gaps leave the class open to silent errors.
88/100
Account Operations
Deposit and withdraw correctly update the balance and log each transaction. Transfer avoids double-counting by updating both balances directly, which is a sound choice. It does not validate that target is a BankAccount instance, so a bad argument would raise an unguarded AttributeError.
22/25
Input Validation
The constructor rejects empty names and negative balances, and both deposit and withdraw guard against invalid amounts. However, account_number receives no validation: an empty string or None is accepted silently. Applying the same checks consistently across all parameters would close this gap.
20/25
Transaction History & Statement
Records are appended after every successful operation and get_statement formats them in a clean columnar layout, correctly reflecting the balance at each step. The only gap is that an account with no transactions produces a statement with an empty body; a simple "no transactions yet" message would handle this edge case.
22/25
Ethyra
Your personal teaching assistant