I’m trying to write a rudimentary banking ATM machine using Python OOP. The exercise I am working on calls for all kinds of advanced features but I am breaking down the task into smaller pieces so it is easier to test and ask questions and build from there.
Right now I am just trying to initialize a starting balance of $0.00 and make basic deposits and withdrawals. If the user tries to withdraw more than their available balance, Python needs to throw a ValueError indicating “Transaction declined.”
Here is my script and test case so far:
class BankAccount: starting_balance = 0.00 # USD def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name def deposit(self, starting_balance, amount): balance = starting_balance + amount return balance def withdraw(self, balance, amount): try: balance = balance - amount except balance <= 0.00: raise ValueError('Transaction declined. Insufficient funds. Deposit some money first.') withdraw(self, balance, amount) else: return balance
Here is me testing the script in my Python REPL:
$ bpython bpython version 0.22.1 on top of Python 3.10.2 /usr/bin/python >>> import script >>> BA = script.BankAccount('Winston', 'Smith') >>> BA.first_name 'Winston' >>> BA.last_name 'Smith' >>> BA.deposit(starting_balance, 100) Traceback (most recent call last): File "<input>", line 1, in <module> BA.deposit(starting_balance, 100) NameError: name 'starting_balance' is not defined >>> BA.deposit(0.00, 100.0) 100.0 >>> BA.withdraw(balance, 25.00) Traceback (most recent call last): File "<input>", line 1, in <module> BA.withdraw(balance, 25.00) NameError: name 'balance' is not defined >>> BA.withdraw(100.00, 25.00) 75.0 >>> BA.withdraw(100.00, 125.00) -25.0 >>>
There are more things that don’t work than what does work.
Here is what works:
- I’m able to import the script and instantiate the class by passing in a first and last name.
- When I invoke the
deposit()method including a $0.00 balance and a $100.00 bill, the method returns the new $100.0 balance.
- When I invoke the
withdraw()method and pass in the $25.00 amount, the method returns $75.00.
Here is what doesn’t work:
- For starters the global constant class attribute variable
starting_balanceis defined as $0.00 so I would think that the default value of $0.00 can be passed into the
deposit()method as the first argument. When I try doing this, Python says it’s not defined (when it clearly is). So anyways, to proceed I pass in $0.00.
- When I attempt to withdraw $25.00 from the new balance, Python says “
balanceis not defined” even though the balance was returned in the previous
deposit()transaction. It’s as if the
balancevalue is not retained. In order to proceed, I pass in the balance of $100.00 and withdraw $25.00 which successfully returns $75.00
- But when I proceed to withdraw $125.00 (amount greater than available balance), Python returns $-25.00 which I tried to prevent and catch with the try/exception mechanism. So this doesn’t work as intended.
My questions are:
- How do I declare the global constant class attribute variable properly so that it is 0.00 and don’t have to redundantly enter
- How do I retain the
balanceattribute after the
deposit()method is called so that I can pass it along when I later attempt to withdraw from that same balance?
- How would you better formulate the try/except mechanism to catch transactions which don’t allow the user to go below $0.00?
This script is part of a non-credit exercise for Fred Baptiste’s Udemy course on Python Object Oriented Programming Deep Dive. I’ve also leveraged resources online such as: oop - What do __init__ and self do in Python? - Stack Overflow and Python Class Attributes: Examples of Variables | Toptal.