I'm trying to update the value of a class variable when someone deposits money in my bank.
My code
class Bank_account():
bank_balance = 0
def __init__(self, name_holder, id, balance):
self.name = name_holder
self.id = id
self.balance = balance
bank_balance += balance
def cash_in(self, cash):
self.balance += cash
bank_balance += cash
def with_draw(self, draw):
if self.balance < draw or bank_balance < draw:
print('Error')
else:
print('Here your money!')
John = Bank_account('John', 123456, 2.10**6)
Smith = Bank_account('Smith', 111111, 3.10**6)
Michael = Bank_account('Michael', 123123, 4.10**6)
Bank_account.bank_balance
My result
UnboundLocalError Traceback (most recent call last)
<ipython-input-30-0a83e2bc19e8> in <module>
19 print('Here your money!')
20
---> 21 Quang = Bank_account('Quang', 123456, 2.10**6)
22 Kien = Bank_account('Kien', 111111, 3.10**6)
23 Trung = Bank_account('Trung', 123123, 4.10**6)
<ipython-input-30-0a83e2bc19e8> in __init__(self, name_holder, id, balance)
7 self.id = id
8 self.balance = balance
----> 9 bank_balance += balance
10
11 def cash_in(self, cash):
UnboundLocalError: local variable 'bank_balance' referenced before assignment
Could anyone tell me how to use class variables and explain my error?
class Bank_account():
def __init__(self, name_holder, id, balance,bank_balance=0):
self.name = name_holder
self.id = id
self.balance = balance
self.bank_balance = balance
def cash_in(self, cash):
self.balance += cash
self.bank_balance += cash
def with_draw(self, draw):
if self.balance < draw or bank_balance < draw:
print('Error')
else:
print('Here your money!')
John = Bank_account('John', 123456, 2.10**6)
Smith = Bank_account('Smith', 111111, 3.10**6)
Michael = Bank_account('Michael', 123123, 4.10**6)
print(John.bank_balance)
I think this is what you are trying to do.
If you absolutely have to, try the following:
(Notice I have added: Bank_account.bank_balance because that initializes the class variable as well. Verify that the output produced is what you want)
class Bank_account:
bank_balance = 0
def __init__(self, name_holder, id, balance):
self.name = name_holder
self.id = id
self.balance = balance
Bank_account.bank_balance += balance # change is here
def cash_in(self, cash):
self.balance += cash
bank_balance += cash
def with_draw(self, draw):
if self.balance < draw or bank_balance < draw:
print('Error')
else:
print('Here your money!')
John = Bank_account('John', 123456, 2.10**6)
Smith = Bank_account('Smith', 111111, 3.10**6)
Michael = Bank_account('Michael', 123123, 4.10**6)
print(Bank_account.bank_balance)
class Bank_account():
bank_balance = 0
def __init__(self, name_holder, id, balance):
self.name = name_holder
self.id = id
self.balance = balance
self.bank_balance += balance
def cash_in(self, cash):
self.balance += cash
bank_balance += cash
def with_draw(self, draw):
if self.balance < draw or bank_balance < draw:
print('Error')
else:
print('Here your money!')
John = Bank_account('John', 123456, 2.1-**6)
Smith = Bank_account('Smith', 111111, 3.10**6)
Michael = Bank_account('Michael', 123123, 4.10**6)
print(John.bank_balance)
Since code inside a class, but outside of methods/functions is not executed, the variable is not declared in the momory. So, the solution would be to declare it in the init method in the following way:
class Bank_account():
def __init__(self, name_holder, id, balance):
# This has been changed
bank_balance = 0
self.name = name_holder
self.id = id
self.balance = balance
bank_balance += balance
def cash_in(self, cash):
self.balance += cash
bank_balance += cash
def with_draw(self, draw):
if self.balance < draw or bank_balance < draw:
print('Error')
else:
print('Here your money!')
John = Bank_account('John', 123456, 2.10**6)
Smith = Bank_account('Smith', 111111, 3.10**6)
Michael = Bank_account('Michael', 123123, 4.10**6)
Bank_account.bank_balance
Or if you want to access the bank balance detached from each bank_account object, just add a line saying global bank_balance in the following manner:
class Bank_account():
def __init__(self, name_holder, id, balance):
# This has been changed
global bank_balance
bank_balance = 0
self.name = name_holder
self.id = id
self.balance = balance
bank_balance += balance
def cash_in(self, cash):
self.balance += cash
bank_balance += cash
def with_draw(self, draw):
if self.balance < draw or bank_balance < draw:
print('Error')
else:
print('Here your money!')
John = Bank_account('John', 123456, 2.10**6)
Smith = Bank_account('Smith', 111111, 3.10**6)
Michael = Bank_account('Michael', 123123, 4.10**6)
Bank_account.bank_balance
But I strongly recommend to add self before the bank_balance variable
Related
I created this simple withdrawal and deposit machine and used a class method for depositing but there seems to be something wrong with it as I expected the return value of the deposit method to be = 20,500 but instead its = None , so what it is the problem here ? and are there any mistakes in my code ?
print("Hello !!! Welcome to Deposit & Withdrawal Machine")
class Account:
withDrawalAmount = 0
depositAmnt = 0
def __init__(self, ID=0, balance=100, annual_interest_rate=0):
self.__ID = ID
self.__balance = balance
self.__annual_interest_rate = annual_interest_rate
#setters
def setId(self, ID):
self.__ID = ID
def setBal(self, Bal):
self.__balance = Bal
def setAnnualInterestRate(self, annualIntrstRate):
self.__annual_interest_rate = annualIntrstRate
#getters
def getId(self):
return self.__ID
def getBal(self):
return self.__balance
def getAnnualIntrstRate(self):
return self.__annual_interest_rate
#special getters
def getMonthlyInterestRate(self):
self.annual_rate = self.__annual_interest_rate / 100
self.monthly_rate = self.annual_rate / 12
return self.monthly_rate
def getMonthlyInterest(self):
return self.__balance * self.monthly_rate
#other methods
def withdraw(self, withDrawalAmount):
if self.__balance >= self.withDrawalAmount:
self.__balance = self.__balance - self.withDrawalAmount
return self.__balance
def deposit(self, depositAmnt ):
if self.depositAmnt >= 1 :
self.__balance = self.__balance + self.depositAmnt
return self.__balance
client001 = Account(1122, 20000, 4.5)
print("Your Balance After withdrawal is : ", client001.withdraw(2500))
print("Your Balance After deposit is : ", client001.deposit(3000))
print("Your Account ID is : ", client001.getId())
print("Your Current Balance is : ", client001.getBal())
print("Your Monthly Intrst Rate is : ", client001.getMonthlyInterestRate())
print("Your Monthly intrst is : ", client001.getMonthlyInterest())
As John already mentioned, to rectify this you need to use the variable depositAmnt in your if statement.
def deposit (self , depositAmnt ):
if depositAmnt >= 1 :
self.__balance = self.__balance + depositAmnt
return self.__balance
right now, the attributes of your class -withDrawalAmount and depositAmnt don't have any usage (since you are inputting them as an argument in your function deposit and withdraw.
You should also change the withdraw function as:
def withdraw (self , withDrawalAmount):
if self.__balance >= withDrawalAmount:
self.__balance = self.__balance - withDrawalAmount
return self.__balance
def deposit (self , depositAmnt ):
if self.depositAmnt >= 1 :
self.__balance = self.__balance + self.depositAmnt
return self.__balance
The amount being deposited is depositAmnt, not self.depositAmnt.
So the if condition is false, therefore the function does not return anything, therefore it returns None by default.
I'm getting the error "AttributeError: 'SavingsAccount' object has no attribute '_SavingsAccount__balance'" when I run this program and I can't work out why. The error is linked to the savings.withdraw() method. Any help would be welcome. It will be clear that I am new to OOP.
import random
class Account:
def __init__(self,holderName,balance):
# generate a 4-digit PIN
self.__PIN=''
for x in range(4):
self.__PIN+=chr(random.randint(48,57))
# generate an 8-digit account number
self.__accountNumber=''
for x in range(8):
self.__accountNumber+=chr(random.randint(48,57))
self.__holderName = holderName
self.__balance = balance
def deposit(self,amount):
self.__balance+=amount
def getBalance(self):
return(self.__balance)
def setBalance(self,amount):
self.__balance = amount
def withdraw(self, amount):
self.__balance -= amount
def setAccountHolder(self,name):
self.__holderName = name
def getAccountHolder(self):
return self.__holderName
def PrintAccountInfo(self):
print('\nPIN: {}'.format(self.__PIN))
print('Account Number: {}'.format(self.__accountNumber))
print('Account Holder: {}'.format(self.__holderName))
print('Balance: £{:.2f}'.format(self.__balance))
class SavingsAccount(Account):
def __init__(self, holderName, balance):
super().__init__(holderName, balance)
self.__withdrawals = 0
def withdraw(self, amount):
if self.__withdrawals < 4:
if self.__balance - amount >= 0.00:
self.__balance -= amount
self.__withdrawals += 1
else:
print('Cannot withdraw - insufficient funds.')
else:
print('You have exceeded the number of withdrawals for this session')
def PrintAccountInfo(self):
super().PrintAccountInfo()
print('Withdrawals: {}'.format(self.__withdrawals))
# main program
main = Account('Joe Smith',400)
main.deposit(100)
main.PrintAccountInfo()
savings = SavingsAccount('Ann Brown',400)
savings.PrintAccountInfo()
savings.withdraw(200)
I'm having a hard time understanding how to initialize an inherited class in python OOP.
I cannot figure out what arguments need to be passed when I initialize it. These are the classes I'm using:
class BankAccount: #parent class
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def withdrawal(self, withdraw):
if withdraw > self.balance:
raise RuntimeError('Sorry, Insufficient Funds!')
else:
print('Withdrawal accepted.')
self.balance -= withdraw
show_balance = input('See account balance? enter y or n: ')
if show_balance == 'y':
print(self.balance)
def deposit(self, amt):
self.balance += amt
print('Deposit Accepted')
show_balance = input('See account balance? enter y or n: ')
if show_balance == 'y':
print(self.balance)
class MinimumBalanceAccount(BankAccount): #child class
minimum_balance = 100
def __init__(self):
BankAccount.__init__(self)
def withdrawal(self, withdraw):
if self.balance - withdraw < self.minimum_balance:
print('Error, balance cannot go below minimum value: {}'.format(minimum_balance))
else:
self.balance -= withdraw
But when I try to initialize the child class:
acc2 = MinimumBalanceAccount('Milind', 1000) # I am not sure what to pass as arguments here
Python gives me this error:
TypeError Traceback (most recent call last)
<ipython-input-9-85e55fb15340> in <module>
----> 1 acc2 = MinimumBalanceAccount('milind', 1000)
TypeError: __init__() takes 1 positional argument but 3 were given
What do I pass in as the arguments?? What's going wrong?
You need to pass the required arguments to the subclass, and to the superclass:
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def withdrawal(self, withdraw):
if withdraw > self.balance:
raise RuntimeError('Sorry, Insufficient Funds!')
else:
print('Withdrawal accepted.')
self.balance -= withdraw
show_balance = input('See account balance? enter y or n: ')
if show_balance == 'y':
print(self.balance)
def deposit(self, amt):
self.balance += amt
print('Deposit Accepted')
show_balance = input('See account balance? enter y or n: ')
if show_balance == 'y':
print(self.balance)
class MinimumBalanceAccount(BankAccount):
minimum_balance = 100
def __init__(self, owner, balance):
super().__init__(owner, balance)
self.minimum_balance = MinimumBalanceAccount.minimum_balance
def withdrawal(self, withdraw):
if self.balance - withdraw < self.minimum_balance:
print('Error, balance cannot go below minimum value: {}'.format(minimum_balance))
else:
self.balance -= withdraw
acc2 = MinimumBalanceAccount('Milind', 1000)
In this case, as pointed out by #Deceze in the comments, you can omit __init__ entirely:
class MinimumBalanceAccount(BankAccount): #child class
minimum_balance = 100
def withdrawal(self, withdraw):
if self.balance - withdraw < self.minimum_balance:
print('Error, balance cannot go below minimum value: {}'.format(minimum_balance))
else:
self.balance -= withdraw
You need to add the initializing parameters also to your child Class when you define the __init__ function and pass it to the parent.
class MinimumBalanceAccount(BankAccount): #child class
minimum_balance = 100
def __init__(self, owner, balance):
BankAccount.__init__(self, owner, balance)
class MinimumBalanceAccount(BankAccount): #child class
minimum_balance = 100
def __init__(self,owner, balance):
BankAccount.__init__(self,owner,balance)
def withdrawal(self, withdraw):
if self.balance - withdraw < self.minimum_balance:
print('Error, balance cannot go below minimum value: {}'.format(minimum_balance))
else:
self.balance -= withdraw
I'm new to Python programming.
I was trying to achieve the following output:
Account c
Account count = 1
Successful transaction! Balance = 10000
Successful transaction! Balance = 9000
Not enough balance
My code:
class Account:
accountCount = 0
def __init__(self, name, accountNo):
self.name = name
self.accountNo = accountNo
self.balance = 0
Account.accountCount += 1
print ("Account " + self.accountNo)
print ("Account count= " +str(Account.accountCount))
def withdraw (self, amount):
self.balance -= amount
return self.balance
def deposit (self,amount):
self.balance += amount
return self.balance
myAccount = Account ("c", "c123")
myAccount.deposit(10000)
myAccount.withdraw(500)
myAccount.withdraw(10000)
I get the following error
line 1, in <module>
line 20, in Account myAccount = Account ("c", "c123")
NameError: name 'Account' is not defined
Your problem is with indentation. Moving your code logic to the beginning of the line will execute your code.
class Account:
accountCount = 0
def __init__(self, name, accountNo):
self.name = name
self.accountNo = accountNo
self.balance = 0
Account.accountCount += 1
print("Account " + self.accountNo)
print("Account count = " + str(Account.accountCount))
def withdraw(self, amount):
self.balance -= amount
return self.balance
def deposit(self, amount):
self.balance += amount
return self.balance
account_c = Account("c", "c123")
account_c.deposit(10000)
account_c.withdraw(500)
account_c.withdraw(10000)
Output:
Account c123
Account count = 1
I have been working on a test and each time I run my code it displays the error code below:
test_savings_account_cannot_withdraw_more_than_current_balance Failure
in line 48, in
test_savings_account_cannot_withdraw_more_than_current_balance
self.assertEquals(message, 'Cannot withdraw beyond the current account
balance', msg='No overdrafts') AssertionError: No overdrafts**
class BankAccount:
def withdraw(self):
pass
def deposit(self):
pass
class SavingsAccount(BankAccount):
def __init__(self, balance=500):
self.balance = balance
def deposit(self, amount):
if (amount <= 0):
return "Invalid deposit amount"
else:
self.balance += amount
return self.balance
def withdraw(self, amount):
if(amount <= 0):
return "Invalid withdraw amount"
elif(self.balance <= 500):
return "Cannot withdraw beyond the minimum account balance"
elif(amount > self.balance):
return "Cannot withdraw beyond the current account balance"
else:
self.balance -= amount
return self.balance
class CurrentAccount(BankAccount):
def __init__(self, balance=0):
self.balance = balance
def deposit(self, amount):
if (amount <= 0):
return "Invalid deposit amount"
else:
self.balance += amount
return self.balance
def withdraw(self, amount):
if (amount <= 0):
return "Invalid withdraw amount"
elif (amount >= self.balance):
return "Cannot withdraw beyond the current account balance"
else:
self.balance -= amount
return self.balance
and the unittest is
import unittest
class CurrentAccountTestCases(unittest.TestCase):
def setUp(self):
self.ca = CurrentAccount()
def tearDown(self):
del self.ca
def test_current_account_is_instance_of_bank_account(self):
self.assertTrue(isinstance(self.ca, BankAccount), msg='CurrentAccount is not a subclass of BankAccount')
def test_current_account_can_deposit_valid_amounts(self):
balance = self.ca.deposit(1500)
self.assertEquals(balance, 1500)
def test_current_account_cannot_withdraw_more_than_current_balance(self):
message = self.ca.withdraw(1500)
self.assertEquals(message, 'Cannot withdraw beyond the current account balance', msg='No overdrafts')
def test_current_account_can_withdraw_valid_cash_amounts(self):
self.ca.deposit(23001)
self.ca.withdraw(437)
self.assertEquals(self.ca.balance, 22564, msg='Incorrect balance after withdrawal')
class SavingsAccountTestCases(unittest.TestCase):
def setUp(self):
self.sa = SavingsAccount()
def tearDown(self):
del self.sa
def test_savings_account_is_instance_of_bank_account(self):
self.assertTrue(isinstance(self.sa, BankAccount), msg='SavingsAccount is not a subclass of BankAccount')
def test_savings_account_can_deposit_valid_amounts(self):
init_balance = self.sa.balance
balance = self.sa.deposit(1500)
self.assertEquals(balance, (1500 + init_balance), msg='Balance does not match deposit')
def test_savings_account_cannot_withdraw_more_than_current_balance(self):
message = self.sa.withdraw(1500)
self.assertEquals(message, 'Cannot withdraw beyond the current account balance', msg='No overdrafts')
def test_savings_account_can_withdraw_valid_amounts_successfully(self):
self.sa.deposit(2300)
self.sa.withdraw(543)
self.assertEquals(2257, self.sa.balance, msg="Incorrect balance after withdrawal")
Because your default balance is 500, and your amount is 1500, so the string you it would return is "Cannot withdraw beyond the minimum account balance" and not the one you expect "Cannot withdraw beyond the current account balance"