Skip to content

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()
63

Overall 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