Index error, can't seem to figure this one out - python

I am totally lost on what to do with this code. But im getting an error on the line
account.append(BankAccount(lst[0],lst[1],float(lst[2]),float(lst[3].replace('\n',''))))
can anyone help me with how to correct this?
Thank you!
FULL CODE:
class BankAccount: #BankAccount class implementation
def __init__(self, ID,PIN,checking,savings):
self.ID = ID
self.PIN = PIN
self.checking = checking
self.savings = savings
def getID(self):
return self.ID
def getPIN(self):
return self.PIN
def getSavings(self):
return self.savings
def getChecking(self):
return self.checking
def withdraw(self,amount,type): #withdraw method returns False if
if(type==1):
#amount is greater than savings balance
if(self.savings<amount):
return False
else: #else deducts amount from savings balance and returns True
self.savings -= amount
elif(type==2):
#amount is greater than savings balance
if(self.checking<amount):
return False
else:
self.checking -= amount
return True
def deposit(self,amount,type):
if(type==1):
self.savings += amount
elif(type==2):
self.checking += amount
def main():
account = []
n=0
with open("accounts.txt") as file: #reads data from file named accounts.txt
for line in file: #reads line by line from file
li = line.split(' ') #splits the line based on ' '
#creates an object of BankAccount and appends it to account list
account.append(BankAccount(li[0],li[1],float(li[2]),float(li[3].replace('\n',''))))
n += 1 #to keep track of number of accounts read from file
userid = input("Enter ID: ")
userpin = input("Enter PIN: ")
i=0
#loops through accounts and performs respective operations
while i<n:
if(account[i].getID()==userid):
if(account[i].getPIN()==userpin):
option = int(input('Enter 1 for withdraw 2 for transfer 3 for balance: '))
if(option==1):
type = int(input('Select type 1. Savings 2.checking: '))
amount = float(input("Enter amount: "))
if(account[i].withdraw(amount,type)):
if(type==1):
print(amount,'withdrawn. Closing balance: ',account[i].getSavings())
else:
print(amount,'withdrwan. Closing balance: ',account[i].getChecking())
else:
print('insufficient funds in your account')
elif(option==2):
option = int(input('Enter 1 for within account transfer 2 for other account: '))
if(option==1): #within account transfer
fromto = int(input('Enter 1. transfer from savings to checking 2. transfer from checking to savings: '))
amount = float(input('Enter amount: '))
if(fromto==1):
account[i].withdraw(amount,1)
account[i].deposit(amount,2)
print('Transfer successful from savings to checking')
else:
account[i].withdraw(amount,2)
account[i].deposit(amount,1)
print('Transfer successful from checking to savings')
else: #other account transfer
accID = input('Enter account ID to transfer money: ')
j=0
while j<n:
if(account[j].getID()==accID):
break
j += 1
if(j<n):
type = int(input('Select type 1. Savings 2.checking: '))
amount = float(input("enter amount: "))
account[i].withdraw(amount,type)
account[j].deposit(amount,type)
print('Transfer successful to account :',account[j].getID())
if(type==1):
print(amount,'transferred. Your savings balance: ',account[i].getSavings())
else:
print(amount,'transferred. Your checking balance: ',account[i].getChecking())
else:
print('Invalid account ID. Transfer of funds terminated.')
else:
type = int(input('Select type 1. Savings 2.checking: '))
if(type==1):
print('Your savings balance:',account[i].getSavings())
else:
print('Your checking balance:',account[i].getChecking())
break
i += 1
if(i==n): #if i reaches n then it's an invalid login
print('invalid login')
else: #writes the account details into the file accounts.txt
file = open('accounts.txt','w')
j=0
while j<n:
file.write(account[j].getID()+' '+account[j].getPIN()+' '+str(account[j].getChecking())+' '+str(account[j].getSavings())+' ')
j += 1
file.close() #closes file stream
print('Thank you!!')
main()

There is most likely a line with less than 4 elements in your accounts.txt file (possibly an empty line at the end).

Related

How to print new balance after adding amount to the initial one?

I'm learning Python and went with a simple ATM code. I've tested it and everything works DownStream - what I mean by this is:
I have a few options when the class is initialized - Balance, Deposit, Withdraw, Exit.
When I run Balance I receive the amount set.
2.1. I go with Deposit - it shows the new amount the person has in their account
2.2. When I use Withdraw I get correct amount as well
Question - When I Deposit and then type Balance I'm getting the initial Balance of the user - that is expected. How can I change the code so after Depositing Money and select Balance to show me the new Balance?
Is this possible to be performed without much complicating the code?
The code:
class User:
def __init__(self):
self.fname = input('Enter your first name: ')
self.lname = input('Enter your last name: ')
self.age = input('Enter your age: ')
def user_details(self):
print('Details:')
print(f"First Name: {self.fname}")
print(f"Last Name: {self.lname}")
print(f"User age: {self.age}")
def deposit_money(self):
self.deposit_amount = 100
return self.deposit_amount
def withdraw_money(self, withdraw_amount):
self.withdraw_amount = withdraw_amount
return self.withdraw_amount
class ATM:
atm_balance = 10000
def __init__(self):
self.machine_balance = self.atm_balance
def user_bank_balance(self):
self.user_balance = 300
print ('Your current balance is ${}'.format(self.user_balance))
def deposit_atm(self, user):
self.total_savings = 0
deposit_m = float(input('How much do you want to deposit? '))
if deposit_m > user.deposit_money():
print('You do not have enough money to deposit')
elif deposit_m == user.deposit_money():
print('Amount deposited: ${}'.format(deposit_m))
self.total_savings = self.user_balance + deposit_m
print('Total amount in your account: ${}'.format(self.total_savings))
def withdraw_atm(self):
savings_left = 0
sum_to_withdraw = float(input('How much do you want to withdraw? '))
if self.atm_balance > sum_to_withdraw and self.user_balance > sum_to_withdraw:
savings_left = self.total_savings - sum_to_withdraw
print("You have withdraw {}".format(sum_to_withdraw))
print('You balance is {}'.format(savings_left))
elif self.atm_balance > sum_to_withdraw and self.user_balance < sum_to_withdraw:
print('Daily limit eceeded')
else:
print('ATM out of service')
class ATMUsage:
#classmethod
def run(cls):
print('Bulbank ATM')
instructions = print("""
Type 'Balance' to check your current balance,
Type 'Deposit' to deposit amount into your account,
Type 'Withdraw' to withdraw from your account,
Type 'Exit' to exit from your account,
""")
active = True
user1 = User()
atm1 = ATM()
user1.user_details()
while active:
selection = input("What would you like to do: 'Balance', 'Deposit', 'Withdraw', 'Exit': ")
if selection == 'Balance'.lower():
atm1.user_bank_balance()
elif selection == 'Deposit'.lower():
atm1.deposit_atm(user1)
elif selection == "Withdraw".lower():
atm1.withdraw_atm()
elif selection == 'Exit'.lower():
print('Thanks for passing by. Have a good one!')
break
else:
print('Wrong selection. Please, try again')
ATMUsage.run()
That's because every time you call the user_bank_balance method, you set the user_balance attribute to 300. So it wouldn't matter what updates you did on the user_balance, whenever you call the user_bank_balance method, you'll get 300
class ATM:
atm_balance = 10000
def __init__(self):
self.machine_balance = self.atm_balance
self.user_balance = 300
def user_bank_balance(self):
print ('Your current balance is ${}'.format(self.user_balance))

How to use sys.exit() if input is equal to specific number

I am looking to correct this code so that when the user inputs 99999 then the code stops running, im also looking to make it so that if the user input is 999 it sets the total to 0
import sys
def money_earned():
total = int()
try: # try open the file
file = open("total.txt", "r")
data = file.readline()
total = int(data)
except: # if file does not exist
file = open("total.txt", "w+") # create file
total = 0
file.close() # close file for now
while True:
try:
pay_this_week = int(input("How much money did you earn this week? "))
break
except ValueError:
print("Oops! That was no valid number. Try again...")
pay_this_week_message = "You've earned £{0} this week!".format(pay_this_week)
total = pay_this_week + total
total_message = "You have earned £{0} in total!".format(total)
print(pay_this_week_message)
print(total_message)
if pay_this_week == "99999":
sys.exit()
file = open("total.txt", "w") # wipe the file and let us write to it
file.write(str(total)) # write the data
file.close() # close the file
money_earned()
So you're taking the input as a string and immediately converting it to an int, but you could actually convert it to an int later and check for some words in your input first.
Right now you have
pay_this_week = int(input("..."))
but if you change this to
input_from_user = input("...")
pay_this_week = int(input_from_user)
then we can add some more code inbetween
input_from_user = input("...")
if input_from_user == "done":
return # this will exit the function and so end execution
elif input_from_user == "reset":
total = 0 # reset the total
else:
pay_this_week = int(input_from_user)
this should have the desired effect

Append CSV cell based user input

Require help: I have a CSV file named 'file_name.csv' containing data as mentioned below. I am building a small bank project (for self-learning) in which I have used :
function open_account - computer asks name and generate random 3 digit account_number and stores it in CSV file
function existing_holder - computer asks account_number and display name which is already stored using open_account function And give the option to deposit or withdraw money
function deposit - computer asks amount to be deposited. And I want it should get appended in particular account_number which he has entered in existing_holder function and display balance.
Output expected: User enter account_number in existing_holder function and the computer asks amount to be deposited and it adds in particular account_number, account_balance
Please correct me what to use in deposit(). I tried using DicWriter, reader, converting them it list but didn't get code working.
Error: TypeError: 'DictWriter' object is not iterable
account_holder_name, account_number, account_balance
Ganesh, 12345, 100
Parvati, 23456, 10000
Waheguru, 98765, 12098
I used below code:
import random as r
import csv
class Account():
print("Welcome to AV Bank")
def __init__(self,choice):
self.choice = choice
self.account_number = 0
self.file_name = 'file_name.csv'
self.header = ('account_holder_name', 'account_number', 'account_balance')
def open_account(self):
self.new_account_holder_name = str(input("Enter new account holder name: "))
self.account_number = r.randrange(999)
self.new_account_deposit = int(input("To open new a/c, deposit minimum Rs.1000/-: "))
if self.new_account_deposit>=1000:
with open(self.file_name, 'a+', newline='') as csvfile:
write_to_file = csv.DictWriter(csvfile, fieldnames=self.header)
# write_to_file.writeheader()
write_to_file.writerow(
{'account_holder_name': self.new_account_holder_name, 'account_number': self.account_number,
'account_balance': self.new_account_deposit})
print(f"Mr.{self.new_account_holder_name} your a/c has been opened and a/c no. is {self.account_number}, With balance Rs. {self.new_account_deposit}/-")
else:
print("Deposit minimum Rs. 1000/-")
def existing_holder(self):
self.account_number = int(input("Enter account holder number: "))
with open(self.file_name, 'r+') as csvfile:
csv_reader = csv.DictReader(csvfile)
for row in csv_reader:
for acn in (row['account_number']):
if int(row['account_number']) == self.account_number:
print(f"Welcome Mr.{row['account_holder_name']}.Please select : \nPress 1 deposit money \nPress 2 for withdraw money")
break
# else:
# print("Enter correct a/c number")
def deposit(self):
self.amount_added = int(input("Enter the amount to be deposited: "))
with open(self.file_name, 'a+') as file:
writeData = csv.DictWriter(file,fieldnames = self.header)
''' WANT TO ITERATE THE CSV FILE TO GET VALUE self.account_number AND UPDATE self.account_balance AFTER DOING ADDITION OPERATION''
# for self.account_number in line:
# if line[self.account_number] == self.account_number:
# print("God")
# with open(self.file_name, 'a+',newline='') as csvfile:
# csv_append = csv.reader(csvfile)
# line = list(csv_append)
#
# print(line)
#self.header = next(csv_append)
# for row in csv_append:
# #self.balance = int(row['account_balance']
# for acn in (row['account_number']):
# if int(row['account_number']) == self.account_number:
# self.balance = int(row['account_balance'])
# self.new_balance = int(row['account_balance']) + self.amount_added
# csv_append.writerow(self.new_balance)
# print(f"Added Rs. {row['account_balance']} in account number {row['account_number']}")
# print(f"A/c balance is Rs.{self.balance}")
# break
# else:
#print("Enter correct a/c number")
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()
if customer_visit ==2:
acct1.existing_holder()
holder_option = int(input())
if holder_option ==1:
acct1.deposit()

sqlite withdraw/deposit function in python

The last stretch of my banking project I've been working on is the deposit/withdraw function. I've gotten most of the other bits working (outside of cleaning up the code) I'm not fully understanding how one adds and subtracts a number from a sql statement inside of python...so here's the part of the code I'm struggling with:
here are my tables:
sqlite_file = 'banking2_db.sqlite'
table_1 = 'Bartertown'
table_2 = 'PINs'
id_column = 'Card_Numbers'
column_1 = 'Character_PINs'
column_2 = 'Balances'
column_3 = 'Card_Numbers'
column_4 = 'Characters'
class LoginPrompt:
def Login(self):
while True:
print(menu[1])
self.Card_number=str(input('>> '))
print(menu[2])
while True:
try:
self.Character_PINs = getpass.getpass('>> ')
self.one_row = c.execute('SELECT * FROM {tn} WHERE {cn}=? and {cnn}=?'.\
format(tn=table_1, cn=column_1, cnn=column_3), (self.Character_PINs, self.Card_number,))
for row in self.one_row.fetchone():
print('Welcome: ', row)
input('Press any key to continue... ')
return
except:
print('PIN incorrect; try again')
break
#MINOR ISSUE, ONLY QUERIES CHAR COLUMN
def loginMenu(self):
while True:
print(menu[5])
print("\n1 - Deposit funds")
print("2 - Withdraw funds")
print("3 - Check balance")
print("4 - Reset Pin")
print("5 - Exit")
while True:
try:
choice = int(input("Please enter a number: "))
except ValueError:
print("Please choose a valid entry")
if choice >= 1 and choice <=5:
choice == 1:
amount = input("\nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
balance = c.execute('UPDATE {tn} SET {cn} = Balances +:amount WHERE Card_Numbers =:self.Card_number' .\
format(tn=table_1, cn=column_2,))
new_bal = balance + (int(amount))
print('${} has been deposited to account {} and the new balance is ${}'.\
format(amount, self.Card_number, balance + (int(amount))))
for row in self.Balances.fetchone():
print('Your new balance is: ', new_bal)
return self.loginMenu()
basically, I'm trying to make sure the program can only pull the balance where the PIN and the Card Number are specified. It selects the balance (This part is working, it is another option in the menu) however, the UPDATE function is still a mystery to me. I understand how to update both the ENTIRE column...on accident, and also how to change the value presented in the Balance field to the value the user submitted ie: the user selects to deposit 100 caps, and then their balance becomes 100 caps. The column I'm trying to update is called Balances, Card_Numbers is the column containing the users "credit card" and amount is the value the user just entered.
Thank you for your help.
edit: added tables, and initial input of the data.
If you want to update the column Balances then your statement should be:
...SET Balances = Balances + :amount...
so do it like this:
c.execute("UPDATE " + table_1 + " SET Balances = Balances + ? WHERE Card_Numbers = ?", (amount, self.Card_number,))
Finally figured it out, silly me.
choice == 1:
amount = input("\nPlease enter the deposit amount: ")
if amount != '' and amount.isdigit():
int(amount)
balance = c.execute('UPDATE {tn} SET {cn} = Balances +:amount WHERE Card_Numbers =:self.Card_number' .\
format(tn=table_1, cn=column_2,))
new_bal = balance + (int(amount))
I was trying to reference it by printing the output of the of the db while it hadn't been committed yet, :eyeroll:
Thank you for the help forpas, it worked like a charm.

Cannot pass returned values from function to another function in python

My goal is to have a small program which checks if a customer is approved for a bank loan. It requires the customer to earn > 30k per year and to have atleast 2 years of experience on his/her current job. The values are get via user input. I implemented regexs to validate the input to be only digits without any strigns or negatives, nor 0.
But the 3rd function asses_customer is always executing the else part. I think everytime the parameters are either None, either 0
here's the source code:
import sys
import re
import logging
import self as self
class loan_qualifier():
# This program determines whether a bank customer
# qualifies for a loan.
def __init__(self): #creates object
pass
def main():
salary_check()
work_exp_check()
asses_customer(salary = 0, years_on_job = 0)
def salary_check():
input_counter = 0 # local variable
# Get the customer's annual salary.
salary = raw_input('Enter your annual salary: ')
salary = re.match(r"(?<![-.])\b[1-9][0-9]*\b", salary)
while not salary:
salary = raw_input('Wrong value. Enter again: ')
salary = re.match(r"(?<![-.])\b[1-9][0-9]*\b", salary)
input_counter += 1
if input_counter >= 6:
print ("No more tries! No loan!")
sys.exit(0)
else:
return salary
def work_exp_check():
input_counter = 0 #local variable to this function
# Get the number of years on the current job.
years_on_job = raw_input('Enter the number of ' +
'years on your current job: ')
years_on_job = re.match(r"(?<![-.])\b[1-9][0-9]*\b", years_on_job)
while not years_on_job:
years_on_job = raw_input('Wrong work experience. Enter again: ')
years_on_job = re.match(r"(?<![-.])\b[1-9][0-9]*\b", years_on_job)
input_counter += 1
if input_counter >= 6:
print ("No more tries! No loan!")
sys.exit(0)
else:
return years_on_job
def asses_customer(salary, years_on_job):
# Determine whether the customer qualifies.
if salary >= 30000.0 or years_on_job >= 2:
print 'You qualify for the loan. '
else:
print 'You do not qualify for this loan. '
# Call main()
main()
You have stated:
It requires the customer to earn > 30k per year and to have at least 2 years of experience on his/her current job.
We can write some simple statements that request a number and if a number is not given then ask for that number again.
The following code is a very simple approach to achieving that goal.
class Loan_Checker():
def __init__(self):
self.salary = 0
self.years_on_job = 0
self.request_salary()
self.request_years()
self.check_if_qualified()
def request_salary(self):
x = raw_input('Enter your annual salary: ')
try:
self.salary = int(x)
except:
print("Please enter a valid number")
self.request_salary()
def request_years(self):
x = raw_input('Enter the number of years on your current job: ')
try:
self.years_on_job = int(x)
except:
print("Please enter a valid number")
self.request_years()
def check_if_qualified(self):
if self.salary >= 30000 and self.years_on_job >= 2:
print 'You qualify for the loan. '
else:
print 'You do not qualify for this loan. '
Loan_Checker()
You have a few errors in your code, and I've refactored it to use the class structure you seemed to want to imply.
import sys
import re
import logging
class loan_qualifier():
# This program determines whether a bank customer
# qualifies for a loan.
def __init__(self): #creates object
self.salary = self.salary_check()
self.years_on_job = self.work_exp_check()
def salary_check(self):
input_counter = 0 # local variable
# Get the customer's annual salary.
salary = None
while salary is None:
if input_counter >= 6:
print ("No more tries! No loan!")
sys.exit(0)
elif input_counter >= 1:
print ("Invalid salary.")
salary = raw_input('Enter your salary: ')
salary = re.match(r"(?<![-.])\b[1-9][0-9]*\b", salary).group(0)
input_counter += 1
# broke out of loop, so valid salary
return salary
def work_exp_check(self):
input_counter = 0 #local variable to this function
# Get the number of years on the current job.
years_on_job = None
while years_on_job is None:
if input_counter >= 6:
print ("No more tries! No loan!")
sys.exit(0)
elif input_counter >= 1:
print ("Invalid year amount")
years_on_job = raw_input('Enter the number of years at your current job: ')
years_on_job = re.match(r"(?<![-.])\b[1-9][0-9]*\b", years_on_job).group(0)
input_counter += 1
# broke out of loop, so valid years_on_job
return years_on_job
def assess_customer(self):
# Determine whether the customer qualifies.
if int(self.salary) >= 30000.0 and int(self.years_on_job) >= 2:
print 'You qualify for the loan. '
else:
print 'You do not qualify for this loan. '
if __name__ == "__main__":
lq = loan_qualifier()
lq.assess_customer()
Some of the errors fixed include the way you were calling assess_customer initially (you were assigning 0's to both values in the function call), as well as the spelling of assess :p. Your condition in assess_customer should also have been an and instead of an or (you wanted both conditions to be true for them to qualify, not for either condition to be true).
You actually don't even really need to do the:
self.salary = self.salary_check()
self.years_on_job = self.work_exp_check()
lines. You could just directly assign the class variables in the functions (i.e. instead of returning, just set self.salary = blah in salary_check). That's kind of a personal choice thing though. I think this makes it clear.
Hopefully this is all clear to you. Let me know if you have any questions. The code can be called by simply typing python NAME_OF_YOUR_FILE.py.
Edit: I didn't realize how broken the salary and years checks were, the new code should fix them.
Edit: Fixed the regex results in this version. My bad.
In this fragment you pass third function always salary = 0 and years_on_job = 0
Try this way:
salary = salary_check()
years_on_job = work_exp_check()
asses_customer(salary, years_on_job)

Categories

Resources