I am new to python and trying to create a small atm like project using classes. I wanna have the user ability to input the amount they want to withdraw and if the amount exceeds the current balance, it prints out that you cannot have negative balance and asks for the input again.
class account:
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
# self.withdraw_amount = withdraw_amount
# self.deposit_amount = deposit_amount
print("{} has {} in his account".format(owner,balance))
def withdraw(self,withdraw_amount):
withdraw_amount = int(input("Enter amount to withdraw: "))
self.withdraw_amount = withdraw_amount
if self.withdraw_amount > self.balance:
print('Balance cannot be negative')
else:
self.final_amount = self.balance - self.withdraw_amount
print("Final Amount after Withdraw " + str(self.final_amount))
def deposit(self,deposit_amount):
deposit_amount = int(input("Enter amount to Deposit: "))
self.deposit_amount = deposit_amount
self.final_balance = self.balance + self.deposit_amount
print("Final Amount after Deposit " + str(self.final_balance))
my_account = account('Samuel',500)
my_account.withdraw(withdraw_amount)
But i am getting the followng error : NameError: name 'withdraw_amount' is not defined
Can someone please point out what i am doing wrong and how can i fix it? Thank you.
As you said, you want to have input inside the function, therefore you don't have to send any input with the function that you are calling.
2nd thing is that you want to force the user to input again if they enter value and this happens
amount exceeds the current balance, it prints out that you cannot have
negative balance and asks for the input again
then you can use a while loop with break condition.
This would work:
class account:
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
# self.withdraw_amount = withdraw_amount
# self.deposit_amount = deposit_amount
print("{} has {} in his account".format(owner,balance))
def withdraw(self):
while True:
try:
withdraw_amount = int(input("Enter amount to withdraw: "))
self.withdraw_amount = withdraw_amount
if self.withdraw_amount > self.balance:
print('Balance cannot be negative')
else:
self.final_amount = self.balance - self.withdraw_amount
print("Final Amount after Withdraw " + str(self.final_amount))
break
except:
print('Incorrect input')
def deposit(self,deposit_amount):
deposit_amount = int(input("Enter amount to Deposit: "))
self.deposit_amount = deposit_amount
self.final_balance = self.balance + self.deposit_amount
print("Final Amount after Deposit " + str(self.final_balance))
my_account = account('Samuel',500)
my_account.withdraw()
You have to give some value instead of passing the variable withdraw_amount
For example:
Your withdraw function have two argument self and withdraw_amount, and when you call it in the line my_account.withdraw(withdraw_amount) you are doing it right but instead of passing variable withdraw_amount just pass some value like 200,300
class account:
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
# self.withdraw_amount = withdraw_amount
# self.deposit_amount = deposit_amount
print("{} has {} in his account".format(owner,balance))
def withdraw(self,withdraw_amount):
withdraw_amount = int(input("Enter amount to withdraw: "))
self.withdraw_amount = withdraw_amount
if self.withdraw_amount > self.balance:
print('Balance cannot be negative')
else:
self.final_amount = self.balance - self.withdraw_amount
print("Final Amount after Withdraw " + str(self.final_amount))
def deposit(self,deposit_amount):
deposit_amount = int(input("Enter amount to Deposit: "))
self.deposit_amount = deposit_amount
self.final_balance = self.balance + self.deposit_amount
print("Final Amount after Deposit " + str(self.final_balance))
my_account = account('Samuel',500)
withdraw_amount = 100
my_account.withdraw(withdraw_amount)
Reason for the error:
withdraw_amount is not defined before my_account.withdraw(withdraw_amount), Try my_account.withdraw(int(input("Enter amount to withdraw: "))) and remove the input() call from the method
Related
I have to write code to instantiate several objects (bank accounts) from a class. I wrote the functions for checking the balance, withdrawing, and depositing with a single object. However, I can't figure how to make it so that the class is repeated for each object. I also can't figure out how to make it so that the choice to check the balance, deposit, or withdraw from the object applies to the correct object. In addition to this, I don't know how to get the functions to check the balance, deposit, and withdraw to run for each object.
Code:
class Account:
def __init__(self, name, account_number, balance):
print("Welcome to the bank.")
self.name=name
self.account_number=account_number
self.balance=balance
def check_balance(self):
print ("Balance:", self.balance)
def deposit(self):
print("Current balance:", self.balance)
str2=input("How much would you like to deposit? ")
str2=int(str2)
print ("Current Balance:", self.balance + str2)
def withdraw(self):
print ("Current Balance", self.balance)
str4=input("How much would you like to withdraw? ")
str4=int(str4)
if self.balance - str4 < 0:
print("Unable to process. Doing this will result in a negative balance.")
elif self.balance - str4 >= 0:
print("Current Balance:", self.balance - str4)
str3=input("Would you like to check the balance of the account, deposit money into the account, or withdraw money from the account? ")
if str3=="check the balance":
self.check_balance()
elif str3=="deposit money":
self.deposit()
elif str3=="withdraw money":
self.withdraw()
else:
print("Unable to process.")
Fred=Account("Fred",20,30)
John=Account("John",30,40)
Michelle=Account("Michelle",40,50)
Ann=Account("Ann",50,60)
You have some design problems here.
Don't store the accounts in 4 separate variables. Store them in a list so you can look them up by account number (or by name, if you want to add that). That will make it easier to save the accounts to file and read them back, which you will need to do.
The Account is just a place to store information. Don't have it do any I/O. Don't have it interact with the user.
You need to ask the user which account to work with.
You should loop until they're done.
Here, I'm asking for an account number every time. To make this smarter, you would ask for an account one, and keep allowing options on that account, with another menu item to switch to a different account.
You COULD store the accounts in a dictionary with the account number as the key. That would be more sensible than a simple list.
class Account:
def __init__(self, name, account_number, balance):
self.name=name
self.account_number=account_number
self.balance=balance
def deposit(self, amt):
self.balance += amt
return self.balance
def withdraw(self,amt):
if self.balance < amt:
return self.balance - amt
self.balance -= amt
return self.balance
accounts = [
Account("Fred",20,30),
Account("John",30,40),
Account("Michelle",40,50),
Account("Ann",50,60)
]
print("Welcome to the bank.")
while True:
acct = int(input("Which account number are you working with today? "))
acct = [a for a in accounts if a.account_number == acct]
if not acct:
print("That account doesn't exist.")
continue
acct = acct[0]
print("\nBalance: ", acct.balance)
print("Would you like to:")
print(" 1. Check the balance")
print(" 2. Deposit money")
print(" 3. Withdraw money")
print(" 4. Quit")
str3 = input("Pick in option: ")
if str3=="1":
print("Balance: ", acct.balance)
elif str3=="2":
amt=int(input("How much would you like to deposit? "))
acct.deposit( amt )
elif str3=="3":
amt=int(input("How much would you like to withdraw? "))
if acct.withdraw( amt ) < 0:
print("Unable to process. Doing this will result in a negative balance.")
elif str3=="4":
break
else:
print("Unrecognized.")
I want to create small bank system in which user enters bank then options would be given to open a new account or use an existing account. Accordingly, functions will be called.
I am using PyCharm IDE ensured whitespace is correct.
My error message, showing that I can't access account_number:
AttributeError: 'Account' object has no attribute 'account_number'
import random as r
class Account():
print("Welcome to AV Bank")
def __init__(self,choice):
self.choice = choice
def open_account(self):
self.new_account_holder_name = str(input("Enter new account holder name: "))
self.account_number = r.randrange(999999)
print(f"Mr.{self.new_account_holder_name} your account has been successfully opened and account number is {self.account_number}, With balance 0. Please deposit minimum R.1000/-")
def existing_holder(self):
self.account_holder_name = str(input("Enter account holder name: "))
print(f"Welcome Mr.{self.account_holder_name}. Following are the choices. Please select : \nPress 1 deposit money \nPress 2 for withdraw money")
def deposit(self,amount_added):
self.balance = 0
self.amount_added = amount_added
self.balance = self.balance + self.amount_added
print(f"Added Rs. {self.amount_added} in account number {self.account_number}")
def withdraw(self,subtract):
self.balance = 0
self.subtract = subtract
if (self.balance<self.subtract):
print("In sufficient balance in account")
else:
self.balance = self.balance - self.subtract
print("Withrawal accepted")
return self.balance
def __str__(self):
return (f"Account Owner: {self.owner} \nAccount Balance: {self.balance}")
customer_visit = int(input("Press 1: To Open New Bank Account or Press 2: To Use Existing Account : "))
acct1 = Account(customer_visit)
if customer_visit ==1:
acct1.open_account()
amount_added = int(input("Enter the deposit amount: "))
acct1.deposit(amount_added)
if customer_visit ==2:
acct1.existing_holder()
holder_option = int(input())
if holder_option ==1:
amount_added = int(input("Enter the deposit amount: "))
acct1.deposit(amount_added)
if holder_option ==2:
withdraw_money = int(input("Enter amount you want to withdraw: "))
acct1.withdraw(withdraw_money)
It is because account_number is not being set as a class attribute. So after the open_account() method is called, it is immediately forgotten. You need to set account_number as an attribute if you would like to call it later on.
def open_account(self):
self.new_account_holder_name = str(input("Enter new account holder name: "))
self.account_number = r.randrange(999999)
My program creates an Account object with an account id of 1122, a balance of $20,000, and an annual interest rate of 4.5%. It uses the withdraw method to withdraw $2,500, the deposit method to deposit $3,000, and print the id, balance, monthly interest rate, and monthly interest.
I am having problems with the next part which is that my program should also ask for the starting values for id, balance, and interest rate. Then it should present a menu where a user can modify their account. After each selection an appropriate message should be displayed. The menu should then be displayed again.
Example Menu:
(1): Display ID
(2): Display Balance
(3): Display Annual Interest Rate
(4): Display Monthly Interest Rate
(5): Display Monthly Interest
(6): Withdraw Money
(7): Deposit Money
(8): Exit
How can I modify my code to function properly with the user input? Right now it is working, but I don't have any code that asks the user for input.
This is the code that I have:
main module:
from Account import Account
def main():
updatedAccount = Account(1122,20000,4.5)
updatedAccount.withdraw(2500)
print("User ID : ", updatedAccount.id)
print("Beginning Balance: ", updatedAccount.balance)
print("Monthly Interest Rate: ", updatedAccount.monthly_interest_rate)
print("Monthly Interest: ", updatedAccount.get_monthly_interest())
main()
Account.py
class Account:
def __init__(self, id, initial_balance=0, rate=4.5):
self.id = id
self.balance = initial_balance
self.annual_interest_rate = rate
#property
def monthly_interest_rate(self):
return self.annual_interest_rate / 12
def get_monthly_interest(self):
return self.balance * self.monthly_interest_rate
def withdraw(self, amount):
if self.balance < amount:
raise ValueError(f"Overdraft, balance less than {amount}")
self.balance -= amount
def deposit(self, amount):
self.balance +=amount
I have tried writing user input for the starting account values, but I am having trouble using it to create the Account object and how to implement the menu.
userid = float(input("Enter User ID: "))
InterestRate = float(input("Enter Interest Rate: "))
balance = float(input("Enter balance: "))
print("User ID is: ", userid)
print("Interest Rate: ", InterestRate)
print("Balance is: ", balance)
You need to user the constructor of Account and provide the values you have
userid = float(input("Enter User ID: ")) // maybe use int() rather than float ?
interestRate = float(input("Enter Interest Rate: "))
balance = float(input("Enter balance: "))
acc = Account(userid, balance, interestRate)
print(acc)
If you override the __str__ method you can print the object just by calling print(acc)
// in Account class
def __str__(self):
return f"ID {self.id},Bal {self.balance}, Rat {self.annual_interest_rate}"
A simple way for the menu can be this, complete the if/elif code in the apply_actions and ad them in the same order in the actions array
def apply_actions(action, account):
if action == 0: # display ID
print(f"Your id is {account.id}")
elif action == 1: # display balance
print(f"Your balance is {account.balance}")
# ...
elif action == 6:
to_deposit = float(input("How many money for the deposit ?"))
account.deposit(to_deposit)
elif action == 7:
exit(1)
else:
print("Bad index")
if __name__ == '__main__':
# ...
acc = Account(userid, balance, interestRate)
actions = ["Display ID", "Display Balance", "Deposit", "Exit"]
while True:
choice = int(input("Choose index in " + str(list(enumerate(actions)))))
apply_actions(choice, acc)
You have two questions, regarding account creation, you do it normally using user input.
userid = float(input("Enter User ID: "))
InterestRate = float(input("Enter Interest Rate: "))
balance = float(input("Enter balance: "))
user_account = Account(userid, balance, InterestRate)
Now, for your menu, you can create a simple function displaying your menu and sending user to each function and when user is done send them back to your menu.
def menu():
possibilities = [(1, "Display ID", "id"), (2, "Display balance", "balance")]
while True:
for possibility in possibilities:
print(f"({possibility[0]}): {possibility[1]}")
User_input = int(input("Please select an option"))
if User_input in [pos[0] for pos in possibilities]:
option, name, attrib = [pos for pos in possibilities if pos[0] == User_input]
print(getattrib(Account, attrib))
else:
print("Option not avaliable")
I am creating an ATM using python code, and I need to create deposit and withdraw functions that behave just like an ATM would. Separately, the deposit and withdraw functions work. However, when I withdraw first then deposit, the balance does not update. Same thing when I deposit then withdraw.
Thank you and your help is much appreciated.
balance = 600
def withdraw(): # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
counter = 0
while counter <= 2:
while counter == 0:
withdraw = int(input("Enter the amount you want to withdraw: AED "))
counter = counter + 1
while ((int(balance) - int(withdraw)) < 0):
print("Error Amount not available in card.")
withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
continue
while ((float(balance) - float(withdraw)) >= 0):
print("Amount left in your account: AED" + str(balance - withdraw))
return (balance - withdraw)
counter = counter + 1
def deposit():
counter = 0
while counter <= 2:
while counter == 0:
deposit = int(input("Enter amount to be deposited: "))
counter = counter + 1
while ((int(balance) + int(deposit)) >= 0):
print("Amount left in your account: AED" + str(balance + deposit))
return (balance + deposit)
counter = counter + 1
withdraw()
deposit()
If I withdraw 17, the balance will be 583. However, when I deposit 12, the balance becomes 612, which is wrong it should be 595.
You are not changing the "balance" variable at all!
Your code should like something like:
balance = withdraw()
balance = deposit()
But there are multiple other problems with your code.
First of all you should not do that many casts. You have to convert your user input one time to a number, then just calculate everything with that type.
Your are using float and int. If you want to stuff with currency, you should use probably decimal (https://docs.python.org/2/library/decimal.html), because floating point arithmetic is not exact for some special cases (you need to round) and integer does obviously not provide floating point arithmetic.
Also your special 'while' usage does not fit common coding standards and makes your code hard to read. Better write one function to get user input and seperate it from the withdrawal() and deposit() logic.
EDIT: Since you seem to be a beginner, I will provide a minimal working solution.
import decimal
balance = 600
def get_user_input(action):
# Get user input and convert it to decimal type
return decimal.Decimal(input("Please enter amount to {} from your account: ".format(action)))
def withdraw():
amount = get_user_input("withdraw")
return balance - amount
def deposit():
amount = get_user_input("deposit")
return balance + amount
print("Your Balance is {} AED".format(balance))
balance = withdraw()
balance = deposit()
print("Your Balance is {} AED".format(balance))
You just forgot to save the new balance, you just print it out
balance = 600
def withdraw(): # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
while True:
withdraw = int(input("Enter amount to be withdrawn: "))
if withdraw > balance:
print("Error Amount not available in card.")
else:
new_balance = balance - withdraw
print("Amount left in your account: AED" + str(new_balance))
return (new_balance)
def deposit():
deposit = int(input("Enter amount to be deposited: "))
new_balance = balance + deposit
print("Amount left in your account: AED" + str(new_balance))
return (new_balance)
# This is the only place you HAVE to change for it to work
balance = withdraw()
balance = deposit()
Took the freedom to change it a bit, but most importantly, you should save the new balance.
I also suggest to make the integer conversion safer, by checking if it is an int before converting it to one.
withdraw_string = input("Enter amount to be withdrawn: ")
try:
withdraw_int = int(withdraw_string)
is_int = True
except ValueError:
print("INVALID INPUT")
is_int = False
if is_int == True:
In both your deposit() and widthdraw() functions, you are never actually touching the variable that holds your balance, that's why you don't see the change.
You have defined the variable balance yet at no point do you ever update that value with balance = balance - x. You are only printing the outcome of that math operation with str(balance + deposit), that code won't actually change your balance.
In order to change your balance you need to update that global variable with balance += widthdraw. But if you put that code in your code, you will get the following error:
UnboundLocalError: local variable 'balance' referenced before assignment
That is because in order to update a global variable from inside a function you need to use the global keyword so that a link is made to the global variable. Docs.
The following code now works, the two important lines are these:
balance -= withdraw
balance += deposit
That's how you are actually modifying the value in the balance variable instead of just seeing the output of the math operation.
balance = 600
def withdraw(): # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
global balance
counter = 0
while counter <= 2:
while counter == 0:
withdraw = int(input("Enter the amount you want to withdraw: AED "))
counter = counter + 1
while ((int(balance) - int(withdraw)) < 0):
print("Error Amount not available in card.")
withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
continue
while ((float(balance) - float(withdraw)) >= 0):
balance -= withdraw
print("Amount left in your account: AED " + str(balance))
return (balance)
counter = counter + 1
def deposit():
global balance
counter = 0
while counter <= 2:
while counter == 0:
deposit = int(input("Enter amount to be deposited: "))
counter = counter + 1
while ((int(balance) + int(deposit)) >= 0):
balance += deposit
print("Amount left in your account: AED" + str(balance))
return balance
counter = counter + 1
withdraw()
deposit()
Disclaimer: You can most definitely remove your return statements from withdraw and deposit since they are essentially useless in this way of solving the problem. Why useless? Because the global variable balance gets modified inside the methods. The return statements would be useful if instead you modified the balance outside the methods. Something like this:
balance = 600
def withdraw(): # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
counter = 0
while counter <= 2:
while counter == 0:
withdraw = int(input("Enter the amount you want to withdraw: AED "))
counter = counter + 1
while ((int(balance) - int(withdraw)) < 0):
print("Error Amount not available in card.")
withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
continue
while ((float(balance) - float(withdraw)) >= 0):
tmp_balance -= withdraw
print("Amount left in your account: AED " + str(tmp_balance))
return tmp_balance
counter = counter + 1
def deposit():
counter = 0
while counter <= 2:
while counter == 0:
deposit = int(input("Enter amount to be deposited: "))
counter = counter + 1
while ((int(balance) + int(deposit)) >= 0):
tmp_balance += deposit
print("Amount left in your account: AED" + str(tmp_balance))
return tmp_balance
counter = counter + 1
balance = withdraw()
balance = deposit()
In this second way, you are manipulating the value of balance based on the returns that the methods provide you. The difference here is that when you call withdraw or deposit you are not actually carrying that out, you won't truly see it reflected until you commit to it with balance = withdraw() . There's a good advantage to doing it this way, which is making sure that no exceptions occur and that if withdraw or deposit completely finished at 100% , then you can commit the changes.
I decided to go a bit further into your code, since you seem to have a whole lot of castings of ints, floats and while loops.
Here's an example of how it could be approached, in case it helps to give anyone more ideas: (remember, there's no single path with code, we all code differently)
Use a decorator to handle int() castings. You can read about decorators here: https://www.python.org/dev/peps/pep-0318/. When you have repeated code (almost copy and paste), that's usually a sign to apply DRY (Don't Repeat Yourself). You can apply DRY by extracting the responsibility to a common function that you can call, or with awesome Python, use decorators. So decorators are nothing but functions, and you can "decorate" functions with them by simply putting #decorator_name. This just means that the decorator will be executed before the call to the decorated function.
I won't be casting to float because in your code you always cast the input to int(). If that's the case, then balance should never be a float.
Make a class called ATM that you can instantiate with a cash_available variable that is the cash in the ATM machine.
Remove fixed while loops (counter =2) and use instead one loop and let the user exit on command.
Extract the responsibility of getting the input for withdraw method, and let user decide whether they want to withdraw again.
Since you are using Python 3, apply f"" string format.
So now the code.
def exit_on_input_cast_error(func):
def wrapper(arg):
try:
return func(arg)
except ValueError as ex:
print("Exiting, bye.")
exit()
return wrapper
class ATM():
"""A simple atm machine"""
def __init__(self, balance):
self.cash_available = balance
#exit_on_input_cast_error
def withdraw(self):
'''Withdraws entered amount, until user exits'''
continue_withdraw = True
while continue_withdraw:
withdraw_amount = self._get_withdraw_input()
self.cash_available -= withdraw_amount
self.print_balance("left in")
withdraw_again = str(input("Would you like to withdraw another amount? (Y or N)"))
continue_withdraw = withdraw_again.lower() in ['1', 'y', 'yes']
self.print_bye()
#exit_on_input_cast_error
def _get_withdraw_input(self):
input_error = True
while input_error:
withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))
if (self.cash_available - withdrawl) < 0:
print("Error Amount not available in machine.")
input_error = True
elif (self.cash_available - withdrawl) > self.cash_available:
print("Error, you can't withdraw a negative amount.")
input_error = True
else:
input_error = False
return withdrawl
#exit_on_input_cast_error
def deposit(self):
input_error = True
while input_error:
depositing = int(input("Please enter the amount you want to deposit (Press N to exit): AED "))
if (self.cash_available + depositing) < self.cash_available:
print("You cannot deposit a negative amount.")
else:
input_error = False
self.cash_available += depositing
self.print_balance("now in")
self.print_bye()
def print_balance(self, custom_insert = 'in'):
print(f"Amount {custom_insert} your account: AED {self.cash_available}")
def print_bye(self):
print("Thank you for using our services today, bye.")
Let's go through it bit by bit.
The decorator is this.:
def exit_on_input_cast_error(func):
def wrapper(arg):
try:
return func(arg)
except ValueError as ex:
print("Exiting, bye.")
exit()
return wrapper
That's just the syntax for a decorator. The important part is the return func(arg). That's the function that will get caught. So this decorator is merely in charge of catching a ValueError exception, which can be thrown when you try to cast something like a int('a'). This decorator is meant to prevent a user trying to withdraw or deposit strings into the atm machine. Since it's code that you will use for both input of withdrawing or depositing, I have placed it as a decorator for ease of call (hello DRY principle).
Next up we have the class constructor. I hope you are familiar with classes, if you are not, there's a lot of links and documentation you can look up so you understand the difference between a class and a method like you had originally. The biggest advantage in this case is that you can have multiple atm's with different amount of cash in each. Or you could instantiate an ATM class, and give it configuration like language, or coin type. Stuff like that.
class ATM():
"""A simple atm machine"""
def __init__(self, balance):
self.cash_available = balance
That's such normal syntax for defining the class. The """A simple atm machine""" is the docstring so that when you call the classes .__doc__ you would get that in return.
Now to the good stuff.
#exit_on_input_cast_error
def _get_withdraw_input(self):
input_error = True
while input_error:
withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))
if (self.cash_available - withdrawl) < 0:
print("Error Amount not available in machine.")
input_error = True
elif (self.cash_available - withdrawl) > self.cash_available:
print("Error, you can't withdraw a negative amount.")
input_error = True
else:
input_error = False
return withdrawl
This method is meant to handle getting the input of the user. See how it's decorated with #exit_on_input_cast_error? That means that if the user puts in 'a' , then the program exits. That's because the int(...) cast will throw that ValueError exception, that the decorator catches. The method does the following in pseudocode:
while there's an error do the following:
Get the user input and cast it as an int.
Make sure the amount user has introduced matches the following criteria:
It is not more than the cash available in the atm.
It is not a negative number.
That's basically what this method does. It keeps asking the user to enter a valid input until either the user does so, or they exit by entering "N". And why do they exit when they enter "N". Because "N" is not an int, so when the cast occurs in this line:
withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))
A ValueError will be thrown by int(), that Exception is then caught by the handy decorator #exit_on_input_cast_error, which then prints "Bye" and exits for you. Cool right?
Next up is the actual withdraw method you had. The difference now is there is only one loop that continues to ask the user if he wants to keep withdrawing again once the action has finished. It's up to the user to either exit or withdraw again.
#exit_on_input_cast_error
def withdraw(self):
'''Withdraws entered amount, until user exits'''
continue_withdraw = True
while continue_withdraw:
withdraw_amount = self._get_withdraw_input()
self.cash_available -= withdraw_amount
self.print_balance("left in")
withdraw_again = str(input("Would you like to withdraw another amount? (Y or N)"))
continue_withdraw = withdraw_again.lower() in ['1', 'y', 'yes']
self.print_bye()
In pseudocode:
while the user wants to withdraw:
Get the user input
Check that the withdraw action does not result in 0 or negative number.
Print the balance
Ask the user if they want to withdraw again.
That's essentially what the method does. And it uses to new methods that are for printing message.
def print_balance(self, custom_insert = 'in'):
print(f"Amount {custom_insert} your account: AED {self.cash_available}")
def print_bye(self):
print("Thank you for using our services today, bye.")
These methods can be called and pass in custom parts of the message, like print_balance. They show the private class variable of the ATM class. In the withdraw method I have to point out that you can withdraw up to the point of reaching 0. The machine will let you try to keep withdrawing but it won't let you since there's 0 cash in it.
And last, the deposit method.
#exit_on_input_cast_error
def deposit(self):
input_error = True
while input_error:
depositing = int(input("Please enter the amount you want to deposit (Press N to exit): AED "))
if (self.cash_available + depositing) < self.cash_available:
print("You cannot deposit a negative amount.")
else:
input_error = False
self.cash_available += depositing
self.print_balance("now in")
self.print_bye()
As you can see, very simple and follows the same principle. Here's how you would call the actual methods:
atm_a = ATM(600)
atm_a.withdraw()
Here's an output of the code:
Enter the amount you want to withdraw (Press N to exit): AED 100
Amount left in your account: AED 500
Would you like to withdraw another amount? (Y or N)Y
Enter the amount you want to withdraw (Press N to exit): AED -1
Error, you can't withdraw a negative amount.
Enter the amount you want to withdraw (Press N to exit): AED 501
Error Amount not available in machine.
Enter the amount you want to withdraw (Press N to exit): AED 5
Amount left in your account: AED 495
Would you like to withdraw another amount? (Y or N)yes
Enter the amount you want to withdraw (Press N to exit): AED 5
Amount left in your account: AED 490
Would you like to withdraw another amount? (Y or N)no
Thank you for using our services today, bye.
If you want to withdraw and deposit:
atm_a = ATM(600)
atm_a.withdraw()
atm_a.deposit()
Here's output of the code:
Enter the amount you want to withdraw (Press N to exit): AED 500
Amount left in your account: AED 100
Would you like to withdraw another amount? (Y or N)no
Thank you for using our services today, bye.
Please enter the amount you want to deposit (Press N to exit): AED -1
You cannot deposit a negative amount.
Please enter the amount you want to deposit (Press N to exit): AED 1000
Amount now in your account: AED 1100
Thank you for using our services today, bye.
Notice how you can only deposit once and then it exists. That's because I didn't implement that, since I already did that for withdraw. Anyone can just replicate it in the deposit if they want.
I hope this wasn't too much and that I managed to explain it. There's loads of things than can be added to this:
Test cases
Difference between cash in ATM physically and balance of the user's account
In withdrawing, knowing if you have the right amount of bills to give the desired amount
...etc
You are not changing the balance variable, you are only returning the value with the added or reduced deposit or withdraw.
Try changing your code so that it saves the new balance before returning it. So instead of:
print("Amount left in your account: AED" + str(balance - withdraw))
return (balance - withdraw)
Try:
balance = (balance - withdraw)
print("Amount left in your account: AED" + str(balance))
return balance
Then do the same with the deposit function.
Your new code:
balance = 600
def withdraw(): # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
counter = 0
while counter <= 2:
while counter == 0:
withdraw = int(input("Enter the amount you want to withdraw: AED "))
counter = counter + 1
while ((int(balance) - int(withdraw)) < 0):
print("Error Amount not available in card.")
withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
continue
while ((float(balance) - float(withdraw)) >= 0):
balance = (balance - withdraw)
print("Amount left in your account: AED" + str(balance))
return balance
counter = counter + 1
def deposit():
counter = 0
while counter <= 2:
while counter == 0:
deposit = int(input("Enter amount to be deposited: "))
counter = counter + 1
while ((int(balance) + int(deposit)) >= 0):
balance = (balance + deposit)
print("Amount left in your account: AED" + str(balance))
return balance
counter = counter + 1
withdraw()
deposit()
I agree with #Chetan Ranpariya's suggestion, you haven't change your balance variable in your code for both function. You can change your balance variable using the expression balance += <increase amount>, balance -= <decrease amount> or balance = balance + <increase amount>, etc.
balance = 600
def withdraw(): # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
counter = 0
while counter <= 2:
while counter == 0:
withdraw = int(input("Enter the amount you want to withdraw: AED "))
counter = counter + 1
while ((int(balance) - int(withdraw)) < 0):
print("Error Amount not available in card.")
withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
continue
while ((float(balance) - float(withdraw)) >= 0):
print("Amount left in your account: AED" + str(balance - withdraw))
return (balance - withdraw)
counter = counter + 1
def deposit():
counter = 0
while counter <= 2:
while counter == 0:
deposit = int(input("Enter amount to be deposited: "))
counter = counter + 1
while ((int(balance) + int(deposit)) >= 0):
print("Amount left in your account: AED" + str(balance + deposit))
return (balance + deposit)
counter = counter + 1
balance = withdraw()
balance = deposit()
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm trying to make a code for my python class and i'm making a wallet management system basic. but i cant get this infinite loop to work. What am i doing wrong?
def main():
# Initial balance
balance = input ('Wallet balance: ')
# This constructs the infinite loop
while true:
# Initial balance
balance = input ('Wallet balance: ')
# Withdraw amount from wallet balance
withdraw= input ('Withdraw amount: ')
#If there is no balance to withdraw from
if balance < 1:
print ('You have no funds to withdraw.')
# Withdraw process and new balance display
if balance > 0:
new = balance - withdraw
print ('Your new balance: '), new
main()
Fixed it for you, it had a few errors
True must be capitalized in Python
If you are passing an int into a str you need to cast the int as a str
Also, I'm not sure why what you're using the main function for? It doesn't pass the initial value into the infinite loop and seems redundant.
def main():
# Initial balance
balance = input ('Wallet balance: ')
# This constructs the infinite loop
while True:
# Initial balance
balance = input('Wallet balance: ')
# Withdraw amount from wallet balance
withdraw= input('Withdraw amount: ')
#If there is no balance to withdraw from
if balance < 1:
print('You have no funds to withdraw.')
# Withdraw process and new balance display
if balance > 0:
new = balance - withdraw
print('Your new balance: ' + str(new))
main()
However, I'm assuming you're trying to build a functional wallet that can withdraw and deposit. I'm not sure how comfortable you are with python and class construction, but I built a fully functional wallet for you to check out and learn from.
class Wallet:
#Grab the initial balance in the account
def __init__(self, initial_balance):
self.balance = initial_balance
#method that deposits funds to the balance
def deposit(self, deposit_amount):
self.balance += deposit_amount
#method that attempts to withdraw from the balance
def withdraw(self, withdraw_amount):
if withdraw_amount <= self.balance:
self.balance -= withdraw_amount
else:
print("Insufficient funds. You have " + str(self.balance) + " in your account. Please deposit more or withdraw less.")
#display the balance
def display_balance(self):
print("The current balance in the account is " + str(self.balance))
print("-----")
#Check if this module is the one currently being run
if __name__ == "__main__":
#Ask user for initial balance
initial_balance = int(input("Initial balance in account: "))
#initiate the class, passing the initial balance
wallet = Wallet(initial_balance)
wallet.display_balance()
while True:
#Pick an option to withdraw, deposit or exit
print("1: Deposit funds")
print("2: Withdraw funds")
print("3: Exit")
type = int(input("Please select an option (1, 2 or 3): "))
if type == 1:
deposit_amount = int(input("Please specify amount to deposit: "))
wallet.deposit(deposit_amount)
wallet.display_balance()
elif type == 2:
withdraw_amount = int(input("Please specify amount to withdraw: "))
wallet.withdraw(withdraw_amount)
wallet.display_balance()
elif type == 3:
break
else:
print("Invalid selection, please type either 1, 2 or 3")
I don't have python3, but this worked in python2 and I added the parentheses around the print-statement after.
def main():
# Initial balance
balance = int(input('Wallet balance: '))
# This constructs the infinite loop
while True:
# Withdraw amount from wallet balance
withdraw = int(input('Withdraw amount: '))
#If there is no balance to withdraw from
if balance < 1:
print ('You have no funds to withdraw.')
# Withdraw process and new balance display
if balance > 0:
new = balance - withdraw
print ('Your new balance: ', new)
main()