I have defined following class of a bank account. The account should always start with 0.0 balance. How can I enforce that the value is always set 0.0 even if the user set it differently at the initiation?
class Account(object):
def __init__(self, name, balance=0.0):
self.name = name
self.balance = balance
def add_money(self, deposit_amnt):
self.balance += deposit_amnt
def withdraw_money(self, withdraw_amnt):
if withdraw_amnt > self.balance:
raise ValueError('Withdraw amount is more than balance')
else:
self.balance -= withdraw_amnt
def check_balance(self):
return self.balance
my_account = Account('Tim', 15)
my_account.check_balance()
>>> 15
You can ommit balance in __init__ if you want to start with 0. You have add method to do that later.
def __init__(self, name):
self.name = name
self.balance = 0
Related
Hello i want to write a test program that creates an Account object with an account id of 1122, a balance of $20,000,and an annual interest rate of 4.5%. Use the withdraw method to withdraw $2,500, use the deposit method to deposit$3,000, and print the id, balance, monthly interest rate, and monthly interest but i keep getting
TypeError: __init__() takes from 1 to 2 positional arguments but 4 were given "
Here is how my code in file with class looks like
class Account:
def __init__(self,id=0,balance=20000,annualInterestRate=4.5):
self.__id = id
def getid(self):
return self.__id
def getbalance(self):
return self.__balance
def getannualInterestRate(self):
return self.__annualInterestRate
def setid(self,id):
self.__id = id
def setbalance(self, balance):
self.__balance = balance
def setannualInterestRate(self, rate):
self.__annualInterestRate = rate
def getMonthlyInterestRate(self):
return self.__annualInterestRate/12
def getMonthlyInterest(self):
return self.__balance * self.getMonthlyInterestRate()
def withdraw(self, amount):
if amount <= self.__balance:
self.__balance -= amount
return True
else:
return False
def deposit(self, amount):
self.__balance +=amount
return balance
and this is how i try to initialize it
from Acc import Account
def main():
updatedAccount = Account(1222,20000,4.5)
updatedAccount.withdraw(2500)
print("User ID : ", updatedAccount.getid())
print("Beginning Balance: ", updatedAccount.getbalance())
print("Monthly Interest Rate: ", updatedAccount.getMonthlyInterestRate())
print("Monthly Interest: ", updatedAccount.getMonthlyInterest())
main()
Can someone please help with the last part of a code where i try to initialize it
Just a thought, why don't you initialize the balance and interest in the init() body?
Then use the setbalance or setters to set the values when the user wants to change the initial value?
Answer to your question: You provided the values to the constructor as positional arguments. Whenever you use the keyword(kwargs) argument construct, remember to explicitly set them in the function call.
Example:
def do_some(i=34, j=23):
Function call:
do_some(i=23,i=12)
This is how your definition of Account should look:
class Account:
# No need for a default id; it should be required
# 0 is a better default for balance; banks don't give you $20,000 unless you specify otherwise :)
def __init__(self, id, initial_balance=0, rate=4.5):
self.id = id
self.balance = initial_balance
self.annual_interest_rate = rate
# Ditch the unnecessary getters and setters
# Example of a "computed attribute value", rather than an explicit method
#property
def monthly_interest_rate(self):
return self.annual_interest_rate / 12
def get_monthly_interest(self):
return self.balance * self.monthly_interest_rate
# Don't return True/False. Do the debit, or raise an exception
def withdraw(self, amount):
if self.balance < amount:
raise ValueError(f"Overdraft, balance less than {amount}")
self.balance -= amount
# Don't return the balance; mutating methods should return None.
# The caller can always check self.balance after the deposit
def deposit(self, amount):
self.balance +=amount
Example usage:
from Acc import Account
def main():
updatedAccount = Account(1222,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()
I am working on a python project. All was working well when I just had one level of inheritance but once I added SavingAccount and CheckingAccount which should be a child of BankAccount which is a child of Customer I started to get the following error: 'CheckingAccount' object has no attribute 'balance'
I assumed I would do the second layer of inheritance the same as the first but maybe I must be missing. Thanks in advance for any help!
class Customer:
def __init__(self,firstName, lastName, social):
self.firstName = firstName
self.lastName = lastName
self.social = social
def setfirstName(self,firstName):
self.firstName = firstName
def setlastName(self,lastName):
self.lastName = lastName
def __str__(self):
self.name = "{},{} (SSN:{})".format(self.firstName, self.lastName,self.social)
return self.name
class BankAccount(Customer):
from random import randint
n = 10
range_start = 10**(n-1)
range_end = (10**n)-1
accountNumber = randint(range_start, range_end)
def __init__(self,customer,balance = 0):
self.customer = customer
self.balance = balance
def setCustomer(self,customer,accountNumber):
self.customer = customer
self.accountNumber = accountNumber
def getCustomer(self,customer,accountNumber):
return self.customer, self.accountNumber
def deposit(self, amount):
self.balance = self.balance + amount
return self.balance
def withdrawal(self, amount):
self.balance = self.balance - amount
return self.balance
def __str__(self):
customer = "{} account number: {}, balance: ${}".format(self.customer,self.accountNumber,self.balance)
return customer
class CheckingAccount(BankAccount):
def __init__(self, bankAccount):
self.bankAccount = bankAccount
def applyAnnualInterest(self):
excess = self.balance - 10000
if excess > 0:
interest = (excess * .02)
self.balance = self.balance + interest
return self.balance
else:
return self.balance
class SavingAccount(BankAccount):
def __init__(self, bankAccount):
self.bankAccount = bankAccount
def applyAnnualInterest(self):
interest = (self.balance * .05)
self.balance = self.balance + interest
return self.balance
def main():
alin = Customer('Alin', 'Smith', '111-11-1111')
mary = Customer('Mary', 'Lee', '222-22-2222')
alinAccnt = CheckingAccount(alin)
maryAccnt = SavingAccount(mary)
alinAccnt.deposit(20000)
print(alinAccnt)
You need to initialise the parent; try:
class CheckingAccount(BankAccount):
def __init__(self, bankAccount):
super(CheckingAccount, self).__init__()
self.bankAccount = bankAccount
Don't forget the intermediate class too!
class BankAccount(Customer):
def __init__(self,customer,balance = 0):
super(BankAccount, self).__init__()
self.customer = customer
self.balance = balance
This will ensure the parent constructors get called too.
I have a class where I'm expecting this:
print(rithesh.amount) = 150.
How can I do this?
Here is my code:
class Customer:
total_amount = 0
def __init__(self, name, mob, email, amount=None):
self.name = name
self.mob = mob
self.eamil = email
def add_amount(self, amount):
self.amount = amount
rithesh = Customer("Rithesh", "8896398598", "ritheshb1#gmail.com")
rithesh.add_amount(100)
rithesh.add_amount(50)
print(rithesh.amount)
You can declare your amount variable in your __init__ method as 0. Then make a small change in your add_amount method.
class Customer:
total_amount = 0
def __init__(self, name, mob, email, amount=None):
self.name = name
self.mob = mob
self.eamil = email
self.amount = 0
def add_amount(self, amount):
self.amount += amount
rithesh = Customer("Rithesh", "8896398598", "ritheshb1#gmail.com")
rithesh.add_amount(100)
rithesh.add_amount(50)
print(rithesh.amount)
output
150
The actual way of having properties in python is by using #property decorator
for example, in your class:
class Customer:
total_amount = 0
def __init__(self, name, mob, email, amount=None):
self.name = name
self.mob = mob
self.eamil = email
#property
def add_amount(self):
return self.add_amount
#add_amount.setter
def add_amount(self, amount):
self.add_amount = amount
rithesh = Customer("Rithesh", "8896398598", "ritheshb1#gmail.com")
rithesh.add_amount = 150
print(rithesh.add_amount)
Got how to do it.
i have to declare the value self.amount = 0 during initialization.
class Customer:
total_amount = 0
def __init__(self, name, mob, email, amount=None):
self.name = name
self.mob = mob
self.eamil = email
self.amount = 0
def add_amount(self, amount):
self.amount += amount
rithesh = Customer("Ritehsh", "8892398598", "ritheshb1#gmail.com")
rithesh.add_amount(100)
rithesh.add_amount(50)
print(rithesh.amount)
hence getting output as print(rithesh.amount) = 150
What is happening is that when you call add_amount you are not adding the value to self.amount you are just setting it.
Just change the definition of add_amount from:
self.amount = amount
to:
self.amount += amount
And add to the __init__ method:
self.amount = 0
Question: Develop a class BankAccount that supports these methods:
__init__(): Initializes the bank account balance to the value of the input argument or to 0 if no input argument is given
withdraw(): Take an argument as an input and withdraws it from the balance
deposit(): Take an amount as an input and add it to the balance
balance(): Returns the balance on the account
class ValueErrorException (Exception):
pass
class BankAccount:
accounts = 0
def __init__ (self, bal = 0.0):
BankAccount.accounts += 1
self.accountNumber = str(BankAccount.accounts)
self.balance = bal
def withdraw(self, amount):
if self.balance - amount < 0:
raise ValueErrorException("Illegal balance")
else:
self.balance -= amount
def deposit (self, amount):
self.balance += amount
def balance(self, amount):
return amount
The balance definition should be like this:
def balance(self):
return self.balance
You may also want to consider changing the variable name from balance to accountBalance so it doesn't affect the definition that is named the same. Your new code would now be:
class ValueErrorException (Exception):
pass
class BankAccount:
accounts = 0
def __init__ (self, bal = 0.0):
BankAccount.accounts += 1
self.accountNumber = str(BankAccount.accounts)
self.accountBalance = bal
def withdraw(self, amount):
if self.accountBalance - amount < 0:
raise ValueErrorException("Illegal balance")
else:
self.accountBalance -= amount
def deposit (self, amount):
self.accountBalance += amount
def balance(self):
return self.accountBalance
return self.balance
access the classes instance variable, not a functional argument. no need to pass amount to a function just to return it
I recently learned Python. I can't catch the error in this code. What is wrong?
class BankAccount:
def __init__(self, initial_balance):
"""Creates an account with the given balance."""
self = [initial_balance, 0]
def deposit(self, amount):
"""Deposits the amount into the account."""
self += amount
def withdraw(self, amount):
"""
Withdraws the amount from the account. Each withdrawal resulting in a
negative balance also deducts a penalty fee of 5 dollars from the balance.
"""
self[0] -= amount
if self[0] < 0:
self[0] -= 5
self[1] += 1
def get_balance(self):
"""Returns the current balance in the account."""
return self[0]
def get_fees(self):
"""Returns the total fees ever deducted from the account."""
return 5*self[1]
my_account = BankAccount(10)
my_account.withdraw(15)
my_account.deposit(20)
my_account.get_balance(), my_account.get_fees()
The error is:
Traceback (most recent call last):
File "C:\Python34\bank.py", line 28, in <module>
my_account.withdraw(15)
File "C:\Python34\bank.py", line 15, in withdraw
self[0] -= amount + 5
TypeError: 'BankAccount' object does not support indexing
self value contains initial_balance and a count of how many withdrawals have happened.
self always refers to the object that calls the class function. So, it is recommended not to assign something to the self variable like:
self = #something
in the constructor. Give that variable a name. Like:
self.details = [initialbalance,0]
And use the variable name wherever.
It should look something like this:
class BankAccount:
OVERDRAW_PENALTY = 5
def __init__(self, opening_balance=0):
self.balance = opening_balance
self.withdrawals = 0
def withdraw(self, amount):
self.withdrawals += 1
self.balance -= amount
if self.balance < 0:
self.balance -= self.OVERDRAW_PENALTY
return amount
Note that I am using self to access instance and class attributes, not trying to assign directly to it. Also, I have factored out the "magic number" 5, so it is clearer what is happening.
Also, your implementation of get_fees is incorrect - the number of withdrawals is currently incremented whether or not a fee is applied. You should either store a self.overdrawn_withdrawals count separately or keep a running total self.fees attribute.
Finally, I have added return amount to the end of withdraw - this allows you to do things like:
account2.deposit(account1.withdraw(100))
to easily transfer money between BankAccounts.
self refers to the BankAccount object. You need to assign and reference instance variables.
Your __init__() method should be something like this:
class BankAccount:
def __init__(self, initial_balance):
"""Creates an account with the given balance."""
self.balance = initial_balance
self.fees = 0
self.withdrawals = 0
def deposit(self, amount):
"""Deposits the amount into the account."""
self.balance += amount
Similarly withdraw() and get_balance() should reference self.balance, and get_fees() should reference self.fees.