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_balance
is defined as $0.00 so I would think that the default value of $0.00 can be passed into thedeposit()
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 “
balance
is not defined” even though the balance was returned in the previousdeposit()
transaction. It’s as if thebalance
value 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
0.00
when invokingdeposit()
? - How do I retain the
balance
attribute after thedeposit()
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.
edit: formatting